Mercurial > projects > dwt-win
annotate dwt/widgets/IME.d @ 297:7d431a32f71e
Fix: IME ole call and string processing.
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Sat, 23 Aug 2008 03:55:06 +0200 |
parents | fd9c62a2998e |
children | 8fa53b71485d |
rev | line source |
---|---|
213 | 1 /******************************************************************************* |
246 | 2 * Copyright (c) 2007, 2008 IBM Corporation and others. |
213 | 3 * All rights reserved. This program and the accompanying materials |
4 * are made available under the terms of the Eclipse Public License v1.0 | |
5 * which accompanies this distribution, and is available at | |
6 * http://www.eclipse.org/legal/epl-v10.html | |
7 * | |
8 * Contributors: | |
9 * IBM Corporation - initial API and implementation | |
10 *******************************************************************************/ | |
11 module dwt.widgets.IME; | |
12 | |
13 | |
14 import dwt.DWT; | |
246 | 15 import dwt.DWTException; |
213 | 16 import dwt.graphics.Color; |
17 import dwt.graphics.TextStyle; | |
18 import dwt.internal.win32.OS; | |
19 import dwt.internal.win32.WINTYPES; | |
20 | |
21 import dwt.widgets.Widget; | |
22 import dwt.widgets.Canvas; | |
23 import dwt.widgets.Event; | |
24 import dwt.widgets.Display; | |
25 | |
26 import dwt.dwthelper.utils; | |
27 | |
28 /** | |
246 | 29 * Instances of this class represent input method editors. |
30 * These are typically in-line pre-edit text areas that allow | |
31 * the user to compose characters from Far Eastern languages | |
32 * such as Japanese, Chinese or Korean. | |
213 | 33 * |
34 * <dl> | |
35 * <dt><b>Styles:</b></dt> | |
36 * <dd>(none)</dd> | |
37 * <dt><b>Events:</b></dt> | |
246 | 38 * <dd>ImeComposition</dd> |
213 | 39 * </dl> |
40 * <p> | |
246 | 41 * IMPORTANT: This class is <em>not</em> intended to be subclassed. |
213 | 42 * </p> |
43 * | |
246 | 44 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> |
45 * | |
213 | 46 * @since 3.4 |
47 */ | |
48 public class IME : Widget { | |
49 Canvas parent; | |
50 int caretOffset; | |
51 int startOffset; | |
52 int commitCount; | |
53 String text; | |
54 int [] ranges; | |
55 TextStyle [] styles; | |
56 | |
57 static const int WM_MSIME_MOUSE; | |
58 | |
59 static byte [16] IID_ITfInputProcessorProfiles; | |
60 static byte [16] IID_ITfDisplayAttributeProvider; | |
61 static byte [16] CLSID_TF_InputProcessorProfiles; | |
62 static byte [16] GUID_TFCAT_TIP_KEYBOARD; | |
63 static this() { | |
64 WM_MSIME_MOUSE = OS.RegisterWindowMessage (StrToTCHARz ("MSIMEMouseOperation")); | |
65 | |
66 OS.IIDFromString ("{1F02B6C5-7842-4EE6-8A0B-9A24183A95CA}\0"w.ptr, IID_ITfInputProcessorProfiles.ptr); | |
67 OS.IIDFromString ("{fee47777-163c-4769-996a-6e9c50ad8f54}\0"w.ptr, IID_ITfDisplayAttributeProvider.ptr); | |
68 OS.IIDFromString ("{33C53A50-F456-4884-B049-85FD643ECFED}\0"w.ptr, CLSID_TF_InputProcessorProfiles.ptr); | |
69 OS.IIDFromString ("{34745C63-B2F0-4784-8B67-5E12C8701A31}\0"w.ptr, GUID_TFCAT_TIP_KEYBOARD.ptr); | |
70 } | |
71 | |
72 /* TextLayout has a copy of these constants */ | |
73 static const int UNDERLINE_IME_DOT = 1 << 16; | |
74 static const int UNDERLINE_IME_DASH = 2 << 16; | |
75 static const int UNDERLINE_IME_THICK = 3 << 16; | |
76 | |
77 /** | |
78 * Prevents uninitialized instances from being created outside the package. | |
79 */ | |
80 this () { | |
81 } | |
82 | |
83 /** | |
246 | 84 * Constructs a new instance of this class given its parent |
85 * and a style value describing its behavior and appearance. | |
86 * <p> | |
87 * The style value is either one of the style constants defined in | |
88 * class <code>DWT</code> which is applicable to instances of this | |
89 * class, or must be built by <em>bitwise OR</em>'ing together | |
90 * (that is, using the <code>int</code> "|" operator) two or more | |
91 * of those <code>DWT</code> style constants. The class description | |
92 * lists the style constants that are applicable to the class. | |
93 * Style bits are also inherited from superclasses. | |
94 * </p> | |
213 | 95 * |
246 | 96 * @param parent a canvas control which will be the parent of the new instance (cannot be null) |
97 * @param style the style of control to construct | |
98 * | |
99 * @exception IllegalArgumentException <ul> | |
100 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> | |
101 * </ul> | |
102 * @exception DWTException <ul> | |
103 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li> | |
104 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li> | |
105 * </ul> | |
106 * | |
107 * @see Widget#checkSubclass | |
108 * @see Widget#getStyle | |
213 | 109 */ |
110 public this (Canvas parent, int style) { | |
111 super (parent, style); | |
112 this.parent = parent; | |
113 createWidget (); | |
114 } | |
115 | |
116 void createWidget () { | |
246 | 117 text = ""; //$NON-NLS-1$ |
213 | 118 startOffset = -1; |
119 if (parent.getIME () is null) { | |
120 parent.setIME (this); | |
121 } | |
122 } | |
123 | |
246 | 124 /** |
125 * Returns the offset of the caret from the start of the document. | |
126 * The caret is within the current composition. | |
127 * | |
128 * @return the caret offset | |
129 * | |
130 * @exception DWTException <ul> | |
131 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
132 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
133 * </ul> | |
134 */ | |
213 | 135 public int getCaretOffset () { |
136 checkWidget (); | |
137 return startOffset + caretOffset; | |
138 } | |
139 | |
246 | 140 /** |
141 * Returns the commit count of the composition. This is the | |
142 * number of characters that have been composed. When the | |
143 * commit count is equal to the length of the composition | |
144 * text, then the in-line edit operation is complete. | |
145 * | |
146 * @return the commit count | |
147 * | |
148 * @exception DWTException <ul> | |
149 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
150 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
151 * </ul> | |
152 * | |
153 * @see IME#getText | |
154 */ | |
213 | 155 public int getCommitCount () { |
156 checkWidget (); | |
157 return commitCount; | |
158 } | |
159 | |
246 | 160 /** |
161 * Returns the offset of the composition from the start of the document. | |
162 * This is the start offset of the composition within the document and | |
163 * in not changed by the input method editor itself during the in-line edit | |
164 * session. | |
165 * | |
166 * @return the offset of the composition | |
167 * | |
168 * @exception DWTException <ul> | |
169 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
170 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
171 * </ul> | |
172 */ | |
213 | 173 public int getCompositionOffset () { |
174 checkWidget (); | |
175 return startOffset; | |
176 } | |
177 | |
178 TF_DISPLAYATTRIBUTE* getDisplayAttribute (short langid, int attInfo) { | |
179 void* pProfiles; | |
180 int hr = OS.CoCreateInstance (CLSID_TF_InputProcessorProfiles.ptr, null, OS.CLSCTX_INPROC_SERVER, IID_ITfInputProcessorProfiles.ptr, &pProfiles); | |
181 TF_DISPLAYATTRIBUTE* pda; | |
182 if (hr is OS.S_OK) { | |
183 byte [16] pclsid; | |
184 byte [16] pguidProfile; | |
185 /* pProfiles.GetDefaultLanguageProfile () */ | |
186 hr = OS.VtblCall (8, pProfiles, cast(int)langid, cast(int)GUID_TFCAT_TIP_KEYBOARD.ptr, cast(int)pclsid.ptr, cast(int)pguidProfile.ptr); | |
187 if (hr is OS.S_OK) { | |
188 void* pProvider; | |
189 hr = OS.CoCreateInstance (pclsid.ptr, null, OS.CLSCTX_INPROC_SERVER, IID_ITfDisplayAttributeProvider.ptr, &pProvider); | |
190 if (hr is OS.S_OK) { | |
191 void* pEnum; | |
192 /* pProvider.EnumDisplayAttributeInfo () */ | |
193 hr = OS.VtblCall (3, pProvider, cast(int)&pEnum); | |
194 if (hr is OS.S_OK) { | |
195 void* pDispInfo; | |
297
7d431a32f71e
Fix: IME ole call and string processing.
Frank Benoit <benoit@tionex.de>
parents:
246
diff
changeset
|
196 TF_DISPLAYATTRIBUTE* tempPda = new TF_DISPLAYATTRIBUTE(); |
213 | 197 /* pEnum.Next () */ |
198 while ((hr = OS.VtblCall (4, pEnum, 1, cast(int) &pDispInfo, 0 )) is OS.S_OK) { | |
199 /* pDispInfo.GetAttributeInfo(); */ | |
297
7d431a32f71e
Fix: IME ole call and string processing.
Frank Benoit <benoit@tionex.de>
parents:
246
diff
changeset
|
200 OS.VtblCall (5, pDispInfo, cast(int)cast(void*)tempPda); |
213 | 201 /* pDispInfo.Release () */ |
202 OS.VtblCall (2, pDispInfo); | |
203 if (tempPda.bAttr is attInfo) { | |
204 pda = tempPda; | |
205 break; | |
206 } | |
207 } | |
208 /* pEnum.Release () */ | |
209 hr = OS.VtblCall (2, pEnum); | |
210 } | |
211 /* pProvider.Release () */ | |
212 hr = OS.VtblCall (2, pProvider); | |
213 } | |
214 } | |
215 /* pProfiles.Release () */ | |
216 hr = OS.VtblCall (2, pProfiles); | |
217 } | |
218 if (pda is null) { | |
219 pda = new TF_DISPLAYATTRIBUTE (); | |
220 switch (attInfo) { | |
221 case OS.TF_ATTR_INPUT: | |
222 pda.lsStyle = OS.TF_LS_SQUIGGLE; | |
223 break; | |
224 case OS.TF_ATTR_CONVERTED: | |
225 case OS.TF_ATTR_TARGET_CONVERTED: | |
226 pda.lsStyle = OS.TF_LS_SOLID; | |
227 pda.fBoldLine = attInfo is OS.TF_ATTR_TARGET_CONVERTED; | |
228 break; | |
214
a8fed3e56433
Fix link error and added missing switch defaults
Frank Benoit <benoit@tionex.de>
parents:
213
diff
changeset
|
229 default: |
213 | 230 } |
231 } | |
232 return pda; | |
233 } | |
234 | |
246 | 235 /** |
236 * Returns the ranges for the style that should be applied during the | |
237 * in-line edit session. | |
238 * <p> | |
239 * The ranges array contains start and end pairs. Each pair refers to | |
240 * the corresponding style in the styles array. For example, the pair | |
241 * that starts at ranges[n] and ends at ranges[n+1] uses the style | |
242 * at styles[n/2] returned by <code>getStyles()</code>. | |
243 * </p> | |
244 * @return the ranges for the styles | |
245 * | |
246 * @exception DWTException <ul> | |
247 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
248 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
249 * </ul> | |
250 * | |
251 * @see IME#getStyles | |
252 */ | |
213 | 253 public int [] getRanges () { |
254 checkWidget (); | |
255 if (ranges is null) return new int [0]; | |
256 int [] result = new int [ranges.length]; | |
257 for (int i = 0; i < result.length; i++) { | |
258 result [i] = ranges [i] + startOffset; | |
259 } | |
260 return result; | |
261 } | |
262 | |
246 | 263 /** |
264 * Returns the styles for the ranges. | |
265 * <p> | |
266 * The ranges array contains start and end pairs. Each pair refers to | |
267 * the corresponding style in the styles array. For example, the pair | |
268 * that starts at ranges[n] and ends at ranges[n+1] uses the style | |
269 * at styles[n/2]. | |
270 * </p> | |
271 * | |
272 * @return the ranges for the styles | |
273 * | |
274 * @exception DWTException <ul> | |
275 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
276 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
277 * </ul> | |
278 * | |
279 * @see IME#getRanges | |
280 */ | |
213 | 281 public TextStyle [] getStyles () { |
282 checkWidget (); | |
283 if (styles is null) return new TextStyle [0]; | |
284 TextStyle [] result = new TextStyle [styles.length]; | |
285 System.arraycopy (styles, 0, result, 0, styles.length); | |
286 return result; | |
287 } | |
288 | |
246 | 289 /** |
290 * Returns the composition text. | |
291 * <p> | |
292 * The text for an IME is the characters in the widget that | |
293 * are in the current composition. When the commit count is | |
294 * equal to the length of the composition text, then the | |
295 * in-line edit operation is complete. | |
296 * </p> | |
297 * | |
298 * @return the widget text | |
299 * | |
300 * @exception DWTException <ul> | |
301 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
302 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
303 * </ul> | |
304 */ | |
213 | 305 public String getText () { |
306 checkWidget (); | |
307 return text; | |
308 } | |
309 | |
246 | 310 /** |
311 * Returns <code>true</code> if the caret should be wide, and | |
312 * <code>false</code> otherwise. In some languages, for example | |
313 * Korean, the caret is typically widened to the width of the | |
314 * current character in the in-line edit session. | |
315 * | |
316 * @return the wide caret state | |
317 * | |
318 * @exception DWTException <ul> | |
319 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
320 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
321 * </ul> | |
322 */ | |
213 | 323 public bool getWideCaret() { |
324 checkWidget (); | |
325 auto layout = OS.GetKeyboardLayout (0); | |
326 short langID = cast(short)OS.LOWORD ( cast(int) layout); | |
327 return OS.PRIMARYLANGID (langID) is OS.LANG_KOREAN; | |
328 } | |
329 | |
330 bool isInlineEnabled () { | |
331 if (OS.IsWinCE || OS.WIN32_VERSION < OS.VERSION (5, 1)) return false; | |
332 return OS.IsDBLocale && hooks (DWT.ImeComposition); | |
333 } | |
334 | |
335 void releaseParent () { | |
336 super.releaseParent (); | |
337 if (this is parent.getIME ()) parent.setIME (null); | |
338 } | |
339 | |
340 void releaseWidget () { | |
341 super.releaseWidget (); | |
342 parent = null; | |
343 text = null; | |
344 styles = null; | |
345 ranges = null; | |
346 } | |
347 | |
246 | 348 /** |
349 * Sets the offset of the composition from the start of the document. | |
350 * This is the start offset of the composition within the document and | |
351 * in not changed by the input method editor itself during the in-line edit | |
352 * session but may need to be changed by clients of the IME. For example, | |
353 * if during an in-line edit operation, a text editor inserts characters | |
354 * above the IME, then the IME must be informed that the composition | |
355 * offset has changed. | |
356 * | |
357 * @return the offset of the composition | |
358 * | |
359 * @exception DWTException <ul> | |
360 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> | |
361 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> | |
362 * </ul> | |
363 */ | |
213 | 364 public void setCompositionOffset (int offset) { |
365 checkWidget (); | |
366 if (offset < 0) return; | |
367 if (startOffset !is -1) { | |
368 startOffset = offset; | |
369 } | |
370 } | |
371 | |
372 LRESULT WM_IME_COMPOSITION (int /*long*/ wParam, int /*long*/ lParam) { | |
373 if (!isInlineEnabled ()) return null; | |
374 ranges = null; | |
375 styles = null; | |
376 caretOffset = commitCount = 0; | |
377 auto hwnd = parent.handle; | |
378 auto hIMC = OS.ImmGetContext (hwnd); | |
379 int codePage = parent.getCodePage (); | |
380 if (hIMC !is null) { | |
381 TCHAR[] buffer = null; | |
382 if ((lParam & OS.GCS_RESULTSTR) !is 0) { | |
383 int length_ = OS.ImmGetCompositionString (hIMC, OS.GCS_RESULTSTR, null, 0); | |
384 if (length_ > 0) { | |
385 buffer = NewTCHARs (codePage, length_ / TCHAR.sizeof); | |
386 OS.ImmGetCompositionString (hIMC, OS.GCS_RESULTSTR, buffer.ptr, length_); | |
387 if (startOffset is -1) { | |
388 Event event = new Event (); | |
389 event.detail = DWT.COMPOSITION_SELECTION; | |
390 sendEvent (DWT.ImeComposition, event); | |
391 startOffset = event.start; | |
392 } | |
393 Event event = new Event (); | |
394 event.detail = DWT.COMPOSITION_CHANGED; | |
395 event.start = startOffset; | |
396 event.end = startOffset + text.length; | |
397 event.text = text = buffer !is null ? TCHARsToStr(buffer) : ""; | |
398 commitCount = text.length ; | |
399 sendEvent (DWT.ImeComposition, event); | |
400 String chars = text; | |
246 | 401 text = ""; //$NON-NLS-1$ |
213 | 402 startOffset = -1; |
403 commitCount = 0; | |
404 if (event.doit) { | |
405 Display display = this.display; | |
406 display.lastKey = 0; | |
407 display.lastVirtual = display.lastNull = display.lastDead = false; | |
297
7d431a32f71e
Fix: IME ole call and string processing.
Frank Benoit <benoit@tionex.de>
parents:
246
diff
changeset
|
408 length_ = chars.codePointCount; |
213 | 409 for (int i = 0; i < length_; i++) { |
297
7d431a32f71e
Fix: IME ole call and string processing.
Frank Benoit <benoit@tionex.de>
parents:
246
diff
changeset
|
410 dchar c = chars[ i .. $ ].firstCodePoint(); |
213 | 411 display.lastAscii = c; |
412 event = new Event (); | |
413 event.character = c; | |
414 parent.sendEvent (DWT.KeyDown, event); | |
415 } | |
416 } | |
417 } | |
418 if ((lParam & OS.GCS_COMPSTR) is 0) return LRESULT.ONE; | |
419 } | |
420 buffer = null; | |
421 if ((lParam & OS.GCS_COMPSTR) !is 0) { | |
422 int length_ = OS.ImmGetCompositionString (hIMC, OS.GCS_COMPSTR, null, 0); | |
423 if (length_ > 0) { | |
424 buffer = NewTCHARs (codePage, length_ / TCHAR.sizeof); | |
425 OS.ImmGetCompositionString (hIMC, OS.GCS_COMPSTR, buffer.ptr, length_); | |
426 if ((lParam & OS.GCS_CURSORPOS) !is 0) { | |
427 caretOffset = OS.ImmGetCompositionString (hIMC, OS.GCS_CURSORPOS, null, 0); | |
428 } | |
429 int [] clauses = null; | |
430 if ((lParam & OS.GCS_COMPCLAUSE) !is 0) { | |
431 length_ = OS.ImmGetCompositionStringW (hIMC, OS.GCS_COMPCLAUSE, /+cast(int [])+/null, 0); | |
432 if (length_ > 0) { | |
433 clauses = new int [length_ / 4]; | |
434 OS.ImmGetCompositionStringW (hIMC, OS.GCS_COMPCLAUSE, clauses.ptr, length_); | |
435 } | |
436 } | |
437 if ((lParam & OS.GCS_COMPATTR) !is 0 && clauses !is null) { | |
438 length_ = OS.ImmGetCompositionStringA (hIMC, OS.GCS_COMPATTR, /+cast(byte [])+/null, 0); | |
439 if (length_ > 0) { | |
440 byte [] attrs = new byte [length_]; | |
441 OS.ImmGetCompositionStringA (hIMC, OS.GCS_COMPATTR, attrs.ptr, length_); | |
442 length_ = clauses.length - 1; | |
443 ranges = new int [length_ * 2]; | |
444 styles = new TextStyle [length_]; | |
445 auto layout = OS.GetKeyboardLayout (0); | |
446 short langID = cast(short)OS.LOWORD ( cast(int) layout); | |
447 TF_DISPLAYATTRIBUTE* attr = null; | |
448 TextStyle style = null; | |
449 for (int i = 0; i < length_; i++) { | |
450 ranges [i * 2] = clauses [i]; | |
451 ranges [i * 2 + 1] = clauses [i + 1] - 1; | |
452 styles [i] = style = new TextStyle (); | |
453 attr = getDisplayAttribute (langID, attrs [clauses [i]]); | |
454 if (attr !is null) { | |
455 switch (attr.crText.type) { | |
456 case OS.TF_CT_COLORREF: | |
457 style.foreground = Color.win32_new (display, attr.crText.cr); | |
458 break; | |
459 case OS.TF_CT_SYSCOLOR: | |
460 int colorRef = OS.GetSysColor (attr.crText.cr); | |
461 style.foreground = Color.win32_new (display, colorRef); | |
462 break; | |
214
a8fed3e56433
Fix link error and added missing switch defaults
Frank Benoit <benoit@tionex.de>
parents:
213
diff
changeset
|
463 default: |
213 | 464 } |
465 switch (attr.crBk.type) { | |
466 case OS.TF_CT_COLORREF: | |
467 style.background = Color.win32_new (display, attr.crBk.cr); | |
468 break; | |
469 case OS.TF_CT_SYSCOLOR: | |
470 int colorRef = OS.GetSysColor (attr.crBk.cr); | |
471 style.background = Color.win32_new (display, colorRef); | |
472 break; | |
214
a8fed3e56433
Fix link error and added missing switch defaults
Frank Benoit <benoit@tionex.de>
parents:
213
diff
changeset
|
473 default: |
213 | 474 } |
475 switch (attr.crLine.type) { | |
476 case OS.TF_CT_COLORREF: | |
477 style.underlineColor = Color.win32_new (display, attr.crLine.cr); | |
478 break; | |
479 case OS.TF_CT_SYSCOLOR: | |
480 int colorRef = OS.GetSysColor (attr.crLine.cr); | |
481 style.underlineColor = Color.win32_new (display, colorRef); | |
482 break; | |
214
a8fed3e56433
Fix link error and added missing switch defaults
Frank Benoit <benoit@tionex.de>
parents:
213
diff
changeset
|
483 default: |
213 | 484 } |
485 style.underline = attr.lsStyle !is OS.TF_LS_NONE; | |
486 switch (attr.lsStyle) { | |
487 case OS.TF_LS_SQUIGGLE: | |
488 style.underlineStyle = DWT.UNDERLINE_SQUIGGLE; | |
489 break; | |
490 case OS.TF_LS_DASH: | |
491 style.underlineStyle = UNDERLINE_IME_DASH; | |
492 break; | |
493 case OS.TF_LS_DOT: | |
494 style.underlineStyle = UNDERLINE_IME_DOT; | |
495 break; | |
496 case OS.TF_LS_SOLID: | |
497 style.underlineStyle = attr.fBoldLine ? UNDERLINE_IME_THICK : DWT.UNDERLINE_SINGLE; | |
498 break; | |
214
a8fed3e56433
Fix link error and added missing switch defaults
Frank Benoit <benoit@tionex.de>
parents:
213
diff
changeset
|
499 default: |
213 | 500 } |
501 } | |
502 } | |
503 } | |
504 } | |
505 } | |
506 OS.ImmReleaseContext (hwnd, hIMC); | |
507 } | |
508 int end = startOffset + text.length; | |
509 if (startOffset is -1) { | |
510 Event event = new Event (); | |
511 event.detail = DWT.COMPOSITION_SELECTION; | |
512 sendEvent (DWT.ImeComposition, event); | |
513 startOffset = event.start; | |
514 end = event.end; | |
515 } | |
516 Event event = new Event (); | |
517 event.detail = DWT.COMPOSITION_CHANGED; | |
518 event.start = startOffset; | |
519 event.end = end; | |
520 event.text = text = buffer !is null ? TCHARsToStr(buffer) : ""; | |
521 sendEvent (DWT.ImeComposition, event); | |
522 if (text.length is 0) { | |
523 startOffset = -1; | |
524 ranges = null; | |
525 styles = null; | |
526 } | |
527 } | |
528 return LRESULT.ONE; | |
529 } | |
530 | |
531 LRESULT WM_IME_COMPOSITION_START (int /*long*/ wParam, int /*long*/ lParam) { | |
532 return isInlineEnabled () ? LRESULT.ONE : null; | |
533 } | |
534 | |
535 LRESULT WM_IME_ENDCOMPOSITION (int /*long*/ wParam, int /*long*/ lParam) { | |
536 return isInlineEnabled () ? LRESULT.ONE : null; | |
537 } | |
538 | |
539 LRESULT WM_KILLFOCUS (int /*long*/ wParam, int /*long*/ lParam) { | |
540 if (!isInlineEnabled ()) return null; | |
541 auto hwnd = parent.handle; | |
542 auto hIMC = OS.ImmGetContext (hwnd); | |
543 if (hIMC !is null) { | |
544 if (OS.ImmGetOpenStatus (hIMC)) { | |
545 OS.ImmNotifyIME (hIMC, OS.NI_COMPOSITIONSTR, OS.CPS_COMPLETE, 0); | |
546 } | |
547 OS.ImmReleaseContext (hwnd, hIMC); | |
548 } | |
549 return null; | |
550 } | |
551 | |
552 LRESULT WM_LBUTTONDOWN (int /*long*/ wParam, int /*long*/ lParam) { | |
553 if (!isInlineEnabled ()) return null; | |
554 auto hwnd = parent.handle; | |
555 auto hIMC = OS.ImmGetContext (hwnd); | |
556 if (hIMC !is null) { | |
557 if (OS.ImmGetOpenStatus (hIMC)) { | |
558 if (OS.ImmGetCompositionString (hIMC, OS.GCS_COMPSTR, null, 0) > 0) { | |
559 Event event = new Event (); | |
560 event.detail = DWT.COMPOSITION_OFFSET; | |
561 event.x = OS.GET_X_LPARAM (lParam); | |
562 event.y = OS.GET_Y_LPARAM (lParam); | |
563 sendEvent (DWT.ImeComposition, event); | |
564 int offset = event.index; | |
565 int length_ = text.length; | |
566 if (offset !is -1 && startOffset !is -1 && startOffset <= offset && offset < startOffset + length_) { | |
567 auto imeWnd = OS.ImmGetDefaultIMEWnd (hwnd); | |
568 offset = event.index + event.count - startOffset; | |
569 int trailing = event.count > 0 ? 1 : 2; | |
570 int /*long*/ param = OS.MAKEWPARAM (OS.MAKEWORD (OS.IMEMOUSE_LDOWN, trailing), offset); | |
571 OS.SendMessage (imeWnd, WM_MSIME_MOUSE, param, hIMC); | |
572 } else { | |
573 OS.ImmNotifyIME (hIMC, OS.NI_COMPOSITIONSTR, OS.CPS_COMPLETE, 0); | |
574 } | |
575 } | |
576 } | |
577 OS.ImmReleaseContext (hwnd, hIMC); | |
578 } | |
579 return null; | |
580 } | |
581 | |
582 } |