Mercurial > projects > dwt-win
annotate dwt/widgets/IME.d @ 214:a8fed3e56433
Fix link error and added missing switch defaults
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Sat, 17 May 2008 19:23:59 +0200 |
parents | 36f5cb12e1a2 |
children | fd9c62a2998e |
rev | line source |
---|---|
213 | 1 /******************************************************************************* |
2 * Copyright (c) 2007 IBM Corporation and others. | |
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; | |
15 import dwt.graphics.Color; | |
16 import dwt.graphics.TextStyle; | |
17 import dwt.internal.win32.OS; | |
18 import dwt.internal.win32.WINTYPES; | |
19 | |
20 import dwt.widgets.Widget; | |
21 import dwt.widgets.Canvas; | |
22 import dwt.widgets.Event; | |
23 import dwt.widgets.Display; | |
24 | |
25 import dwt.dwthelper.utils; | |
26 | |
27 /** | |
28 * TODO - JAVA DOC | |
29 * | |
30 * <dl> | |
31 * <dt><b>Styles:</b></dt> | |
32 * <dd>(none)</dd> | |
33 * <dt><b>Events:</b></dt> | |
34 * <dd>(none)</dd> | |
35 * </dl> | |
36 * <p> | |
37 * . | |
38 * </p> | |
39 * | |
40 * @since 3.4 | |
41 */ | |
42 | |
43 public class IME : Widget { | |
44 Canvas parent; | |
45 int caretOffset; | |
46 int startOffset; | |
47 int commitCount; | |
48 String text; | |
49 int [] ranges; | |
50 TextStyle [] styles; | |
51 | |
52 static const int WM_MSIME_MOUSE; | |
53 | |
54 static byte [16] IID_ITfInputProcessorProfiles; | |
55 static byte [16] IID_ITfDisplayAttributeProvider; | |
56 static byte [16] CLSID_TF_InputProcessorProfiles; | |
57 static byte [16] GUID_TFCAT_TIP_KEYBOARD; | |
58 static this() { | |
59 WM_MSIME_MOUSE = OS.RegisterWindowMessage (StrToTCHARz ("MSIMEMouseOperation")); | |
60 | |
61 OS.IIDFromString ("{1F02B6C5-7842-4EE6-8A0B-9A24183A95CA}\0"w.ptr, IID_ITfInputProcessorProfiles.ptr); | |
62 OS.IIDFromString ("{fee47777-163c-4769-996a-6e9c50ad8f54}\0"w.ptr, IID_ITfDisplayAttributeProvider.ptr); | |
63 OS.IIDFromString ("{33C53A50-F456-4884-B049-85FD643ECFED}\0"w.ptr, CLSID_TF_InputProcessorProfiles.ptr); | |
64 OS.IIDFromString ("{34745C63-B2F0-4784-8B67-5E12C8701A31}\0"w.ptr, GUID_TFCAT_TIP_KEYBOARD.ptr); | |
65 } | |
66 | |
67 /* TextLayout has a copy of these constants */ | |
68 static const int UNDERLINE_IME_DOT = 1 << 16; | |
69 static const int UNDERLINE_IME_DASH = 2 << 16; | |
70 static const int UNDERLINE_IME_THICK = 3 << 16; | |
71 | |
72 /** | |
73 * Prevents uninitialized instances from being created outside the package. | |
74 */ | |
75 this () { | |
76 } | |
77 | |
78 /** | |
79 * | |
80 * @see DWT | |
81 */ | |
82 public this (Canvas parent, int style) { | |
83 super (parent, style); | |
84 this.parent = parent; | |
85 createWidget (); | |
86 } | |
87 | |
88 void createWidget () { | |
89 text = ""; | |
90 startOffset = -1; | |
91 if (parent.getIME () is null) { | |
92 parent.setIME (this); | |
93 } | |
94 } | |
95 | |
96 public int getCaretOffset () { | |
97 checkWidget (); | |
98 return startOffset + caretOffset; | |
99 } | |
100 | |
101 public int getCommitCount () { | |
102 checkWidget (); | |
103 return commitCount; | |
104 } | |
105 | |
106 public int getCompositionOffset () { | |
107 checkWidget (); | |
108 return startOffset; | |
109 } | |
110 | |
111 TF_DISPLAYATTRIBUTE* getDisplayAttribute (short langid, int attInfo) { | |
112 void* pProfiles; | |
113 int hr = OS.CoCreateInstance (CLSID_TF_InputProcessorProfiles.ptr, null, OS.CLSCTX_INPROC_SERVER, IID_ITfInputProcessorProfiles.ptr, &pProfiles); | |
114 TF_DISPLAYATTRIBUTE* pda; | |
115 if (hr is OS.S_OK) { | |
116 byte [16] pclsid; | |
117 byte [16] pguidProfile; | |
118 /* pProfiles.GetDefaultLanguageProfile () */ | |
119 hr = OS.VtblCall (8, pProfiles, cast(int)langid, cast(int)GUID_TFCAT_TIP_KEYBOARD.ptr, cast(int)pclsid.ptr, cast(int)pguidProfile.ptr); | |
120 if (hr is OS.S_OK) { | |
121 void* pProvider; | |
122 hr = OS.CoCreateInstance (pclsid.ptr, null, OS.CLSCTX_INPROC_SERVER, IID_ITfDisplayAttributeProvider.ptr, &pProvider); | |
123 if (hr is OS.S_OK) { | |
124 void* pEnum; | |
125 /* pProvider.EnumDisplayAttributeInfo () */ | |
126 hr = OS.VtblCall (3, pProvider, cast(int)&pEnum); | |
127 if (hr is OS.S_OK) { | |
128 void* pDispInfo; | |
129 TF_DISPLAYATTRIBUTE* tempPda; | |
130 /* pEnum.Next () */ | |
131 while ((hr = OS.VtblCall (4, pEnum, 1, cast(int) &pDispInfo, 0 )) is OS.S_OK) { | |
132 /* pDispInfo.GetAttributeInfo(); */ | |
133 OS.VtblCall (5, pDispInfo, cast(int)&tempPda); | |
134 /* pDispInfo.Release () */ | |
135 OS.VtblCall (2, pDispInfo); | |
136 if (tempPda.bAttr is attInfo) { | |
137 pda = tempPda; | |
138 break; | |
139 } | |
140 } | |
141 /* pEnum.Release () */ | |
142 hr = OS.VtblCall (2, pEnum); | |
143 } | |
144 /* pProvider.Release () */ | |
145 hr = OS.VtblCall (2, pProvider); | |
146 } | |
147 } | |
148 /* pProfiles.Release () */ | |
149 hr = OS.VtblCall (2, pProfiles); | |
150 } | |
151 if (pda is null) { | |
152 pda = new TF_DISPLAYATTRIBUTE (); | |
153 switch (attInfo) { | |
154 case OS.TF_ATTR_INPUT: | |
155 pda.lsStyle = OS.TF_LS_SQUIGGLE; | |
156 break; | |
157 case OS.TF_ATTR_CONVERTED: | |
158 case OS.TF_ATTR_TARGET_CONVERTED: | |
159 pda.lsStyle = OS.TF_LS_SOLID; | |
160 pda.fBoldLine = attInfo is OS.TF_ATTR_TARGET_CONVERTED; | |
161 break; | |
214
a8fed3e56433
Fix link error and added missing switch defaults
Frank Benoit <benoit@tionex.de>
parents:
213
diff
changeset
|
162 default: |
213 | 163 } |
164 } | |
165 return pda; | |
166 } | |
167 | |
168 public int [] getRanges () { | |
169 checkWidget (); | |
170 if (ranges is null) return new int [0]; | |
171 int [] result = new int [ranges.length]; | |
172 for (int i = 0; i < result.length; i++) { | |
173 result [i] = ranges [i] + startOffset; | |
174 } | |
175 return result; | |
176 } | |
177 | |
178 public TextStyle [] getStyles () { | |
179 checkWidget (); | |
180 if (styles is null) return new TextStyle [0]; | |
181 TextStyle [] result = new TextStyle [styles.length]; | |
182 System.arraycopy (styles, 0, result, 0, styles.length); | |
183 return result; | |
184 } | |
185 | |
186 public String getText () { | |
187 checkWidget (); | |
188 return text; | |
189 } | |
190 | |
191 public bool getWideCaret() { | |
192 checkWidget (); | |
193 auto layout = OS.GetKeyboardLayout (0); | |
194 short langID = cast(short)OS.LOWORD ( cast(int) layout); | |
195 return OS.PRIMARYLANGID (langID) is OS.LANG_KOREAN; | |
196 } | |
197 | |
198 bool isInlineEnabled () { | |
199 if (OS.IsWinCE || OS.WIN32_VERSION < OS.VERSION (5, 1)) return false; | |
200 return OS.IsDBLocale && hooks (DWT.ImeComposition); | |
201 } | |
202 | |
203 void releaseParent () { | |
204 super.releaseParent (); | |
205 if (this is parent.getIME ()) parent.setIME (null); | |
206 } | |
207 | |
208 void releaseWidget () { | |
209 super.releaseWidget (); | |
210 parent = null; | |
211 text = null; | |
212 styles = null; | |
213 ranges = null; | |
214 } | |
215 | |
216 public void setCompositionOffset (int offset) { | |
217 checkWidget (); | |
218 if (offset < 0) return; | |
219 if (startOffset !is -1) { | |
220 startOffset = offset; | |
221 } | |
222 } | |
223 | |
224 LRESULT WM_IME_COMPOSITION (int /*long*/ wParam, int /*long*/ lParam) { | |
225 if (!isInlineEnabled ()) return null; | |
226 ranges = null; | |
227 styles = null; | |
228 caretOffset = commitCount = 0; | |
229 auto hwnd = parent.handle; | |
230 auto hIMC = OS.ImmGetContext (hwnd); | |
231 int codePage = parent.getCodePage (); | |
232 if (hIMC !is null) { | |
233 TCHAR[] buffer = null; | |
234 if ((lParam & OS.GCS_RESULTSTR) !is 0) { | |
235 int length_ = OS.ImmGetCompositionString (hIMC, OS.GCS_RESULTSTR, null, 0); | |
236 if (length_ > 0) { | |
237 buffer = NewTCHARs (codePage, length_ / TCHAR.sizeof); | |
238 OS.ImmGetCompositionString (hIMC, OS.GCS_RESULTSTR, buffer.ptr, length_); | |
239 if (startOffset is -1) { | |
240 Event event = new Event (); | |
241 event.detail = DWT.COMPOSITION_SELECTION; | |
242 sendEvent (DWT.ImeComposition, event); | |
243 startOffset = event.start; | |
244 } | |
245 Event event = new Event (); | |
246 event.detail = DWT.COMPOSITION_CHANGED; | |
247 event.start = startOffset; | |
248 event.end = startOffset + text.length; | |
249 event.text = text = buffer !is null ? TCHARsToStr(buffer) : ""; | |
250 commitCount = text.length ; | |
251 sendEvent (DWT.ImeComposition, event); | |
252 String chars = text; | |
253 text = ""; | |
254 startOffset = -1; | |
255 commitCount = 0; | |
256 if (event.doit) { | |
257 Display display = this.display; | |
258 display.lastKey = 0; | |
259 display.lastVirtual = display.lastNull = display.lastDead = false; | |
260 length_ = chars.length; | |
261 for (int i = 0; i < length_; i++) { | |
262 char c = chars.charAt (i); | |
263 display.lastAscii = c; | |
264 event = new Event (); | |
265 event.character = c; | |
266 parent.sendEvent (DWT.KeyDown, event); | |
267 } | |
268 } | |
269 } | |
270 if ((lParam & OS.GCS_COMPSTR) is 0) return LRESULT.ONE; | |
271 } | |
272 buffer = null; | |
273 if ((lParam & OS.GCS_COMPSTR) !is 0) { | |
274 int length_ = OS.ImmGetCompositionString (hIMC, OS.GCS_COMPSTR, null, 0); | |
275 if (length_ > 0) { | |
276 buffer = NewTCHARs (codePage, length_ / TCHAR.sizeof); | |
277 OS.ImmGetCompositionString (hIMC, OS.GCS_COMPSTR, buffer.ptr, length_); | |
278 if ((lParam & OS.GCS_CURSORPOS) !is 0) { | |
279 caretOffset = OS.ImmGetCompositionString (hIMC, OS.GCS_CURSORPOS, null, 0); | |
280 } | |
281 int [] clauses = null; | |
282 if ((lParam & OS.GCS_COMPCLAUSE) !is 0) { | |
283 length_ = OS.ImmGetCompositionStringW (hIMC, OS.GCS_COMPCLAUSE, /+cast(int [])+/null, 0); | |
284 if (length_ > 0) { | |
285 clauses = new int [length_ / 4]; | |
286 OS.ImmGetCompositionStringW (hIMC, OS.GCS_COMPCLAUSE, clauses.ptr, length_); | |
287 } | |
288 } | |
289 if ((lParam & OS.GCS_COMPATTR) !is 0 && clauses !is null) { | |
290 length_ = OS.ImmGetCompositionStringA (hIMC, OS.GCS_COMPATTR, /+cast(byte [])+/null, 0); | |
291 if (length_ > 0) { | |
292 byte [] attrs = new byte [length_]; | |
293 OS.ImmGetCompositionStringA (hIMC, OS.GCS_COMPATTR, attrs.ptr, length_); | |
294 length_ = clauses.length - 1; | |
295 ranges = new int [length_ * 2]; | |
296 styles = new TextStyle [length_]; | |
297 auto layout = OS.GetKeyboardLayout (0); | |
298 short langID = cast(short)OS.LOWORD ( cast(int) layout); | |
299 TF_DISPLAYATTRIBUTE* attr = null; | |
300 TextStyle style = null; | |
301 for (int i = 0; i < length_; i++) { | |
302 ranges [i * 2] = clauses [i]; | |
303 ranges [i * 2 + 1] = clauses [i + 1] - 1; | |
304 styles [i] = style = new TextStyle (); | |
305 attr = getDisplayAttribute (langID, attrs [clauses [i]]); | |
306 if (attr !is null) { | |
307 switch (attr.crText.type) { | |
308 case OS.TF_CT_COLORREF: | |
309 style.foreground = Color.win32_new (display, attr.crText.cr); | |
310 break; | |
311 case OS.TF_CT_SYSCOLOR: | |
312 int colorRef = OS.GetSysColor (attr.crText.cr); | |
313 style.foreground = Color.win32_new (display, colorRef); | |
314 break; | |
214
a8fed3e56433
Fix link error and added missing switch defaults
Frank Benoit <benoit@tionex.de>
parents:
213
diff
changeset
|
315 default: |
213 | 316 } |
317 switch (attr.crBk.type) { | |
318 case OS.TF_CT_COLORREF: | |
319 style.background = Color.win32_new (display, attr.crBk.cr); | |
320 break; | |
321 case OS.TF_CT_SYSCOLOR: | |
322 int colorRef = OS.GetSysColor (attr.crBk.cr); | |
323 style.background = Color.win32_new (display, colorRef); | |
324 break; | |
214
a8fed3e56433
Fix link error and added missing switch defaults
Frank Benoit <benoit@tionex.de>
parents:
213
diff
changeset
|
325 default: |
213 | 326 } |
327 switch (attr.crLine.type) { | |
328 case OS.TF_CT_COLORREF: | |
329 style.underlineColor = Color.win32_new (display, attr.crLine.cr); | |
330 break; | |
331 case OS.TF_CT_SYSCOLOR: | |
332 int colorRef = OS.GetSysColor (attr.crLine.cr); | |
333 style.underlineColor = Color.win32_new (display, colorRef); | |
334 break; | |
214
a8fed3e56433
Fix link error and added missing switch defaults
Frank Benoit <benoit@tionex.de>
parents:
213
diff
changeset
|
335 default: |
213 | 336 } |
337 style.underline = attr.lsStyle !is OS.TF_LS_NONE; | |
338 switch (attr.lsStyle) { | |
339 case OS.TF_LS_SQUIGGLE: | |
340 style.underlineStyle = DWT.UNDERLINE_SQUIGGLE; | |
341 break; | |
342 case OS.TF_LS_DASH: | |
343 style.underlineStyle = UNDERLINE_IME_DASH; | |
344 break; | |
345 case OS.TF_LS_DOT: | |
346 style.underlineStyle = UNDERLINE_IME_DOT; | |
347 break; | |
348 case OS.TF_LS_SOLID: | |
349 style.underlineStyle = attr.fBoldLine ? UNDERLINE_IME_THICK : DWT.UNDERLINE_SINGLE; | |
350 break; | |
214
a8fed3e56433
Fix link error and added missing switch defaults
Frank Benoit <benoit@tionex.de>
parents:
213
diff
changeset
|
351 default: |
213 | 352 } |
353 } | |
354 } | |
355 } | |
356 } | |
357 } | |
358 OS.ImmReleaseContext (hwnd, hIMC); | |
359 } | |
360 int end = startOffset + text.length; | |
361 if (startOffset is -1) { | |
362 Event event = new Event (); | |
363 event.detail = DWT.COMPOSITION_SELECTION; | |
364 sendEvent (DWT.ImeComposition, event); | |
365 startOffset = event.start; | |
366 end = event.end; | |
367 } | |
368 Event event = new Event (); | |
369 event.detail = DWT.COMPOSITION_CHANGED; | |
370 event.start = startOffset; | |
371 event.end = end; | |
372 event.text = text = buffer !is null ? TCHARsToStr(buffer) : ""; | |
373 sendEvent (DWT.ImeComposition, event); | |
374 if (text.length is 0) { | |
375 startOffset = -1; | |
376 ranges = null; | |
377 styles = null; | |
378 } | |
379 } | |
380 return LRESULT.ONE; | |
381 } | |
382 | |
383 LRESULT WM_IME_COMPOSITION_START (int /*long*/ wParam, int /*long*/ lParam) { | |
384 return isInlineEnabled () ? LRESULT.ONE : null; | |
385 } | |
386 | |
387 LRESULT WM_IME_ENDCOMPOSITION (int /*long*/ wParam, int /*long*/ lParam) { | |
388 return isInlineEnabled () ? LRESULT.ONE : null; | |
389 } | |
390 | |
391 LRESULT WM_KILLFOCUS (int /*long*/ wParam, int /*long*/ lParam) { | |
392 if (!isInlineEnabled ()) return null; | |
393 auto hwnd = parent.handle; | |
394 auto hIMC = OS.ImmGetContext (hwnd); | |
395 if (hIMC !is null) { | |
396 if (OS.ImmGetOpenStatus (hIMC)) { | |
397 OS.ImmNotifyIME (hIMC, OS.NI_COMPOSITIONSTR, OS.CPS_COMPLETE, 0); | |
398 } | |
399 OS.ImmReleaseContext (hwnd, hIMC); | |
400 } | |
401 return null; | |
402 } | |
403 | |
404 LRESULT WM_LBUTTONDOWN (int /*long*/ wParam, int /*long*/ lParam) { | |
405 if (!isInlineEnabled ()) return null; | |
406 auto hwnd = parent.handle; | |
407 auto hIMC = OS.ImmGetContext (hwnd); | |
408 if (hIMC !is null) { | |
409 if (OS.ImmGetOpenStatus (hIMC)) { | |
410 if (OS.ImmGetCompositionString (hIMC, OS.GCS_COMPSTR, null, 0) > 0) { | |
411 Event event = new Event (); | |
412 event.detail = DWT.COMPOSITION_OFFSET; | |
413 event.x = OS.GET_X_LPARAM (lParam); | |
414 event.y = OS.GET_Y_LPARAM (lParam); | |
415 sendEvent (DWT.ImeComposition, event); | |
416 int offset = event.index; | |
417 int length_ = text.length; | |
418 if (offset !is -1 && startOffset !is -1 && startOffset <= offset && offset < startOffset + length_) { | |
419 auto imeWnd = OS.ImmGetDefaultIMEWnd (hwnd); | |
420 offset = event.index + event.count - startOffset; | |
421 int trailing = event.count > 0 ? 1 : 2; | |
422 int /*long*/ param = OS.MAKEWPARAM (OS.MAKEWORD (OS.IMEMOUSE_LDOWN, trailing), offset); | |
423 OS.SendMessage (imeWnd, WM_MSIME_MOUSE, param, hIMC); | |
424 } else { | |
425 OS.ImmNotifyIME (hIMC, OS.NI_COMPOSITIONSTR, OS.CPS_COMPLETE, 0); | |
426 } | |
427 } | |
428 } | |
429 OS.ImmReleaseContext (hwnd, hIMC); | |
430 } | |
431 return null; | |
432 } | |
433 | |
434 } |