Mercurial > projects > dwt-win
comparison dwt/widgets/IME.d @ 213:36f5cb12e1a2
Update to SWT 3.4M7
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Sat, 17 May 2008 17:34:28 +0200 |
parents | |
children | a8fed3e56433 |
comparison
equal
deleted
inserted
replaced
212:ab60f3309436 | 213:36f5cb12e1a2 |
---|---|
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; | |
162 } | |
163 } | |
164 return pda; | |
165 } | |
166 | |
167 public int [] getRanges () { | |
168 checkWidget (); | |
169 if (ranges is null) return new int [0]; | |
170 int [] result = new int [ranges.length]; | |
171 for (int i = 0; i < result.length; i++) { | |
172 result [i] = ranges [i] + startOffset; | |
173 } | |
174 return result; | |
175 } | |
176 | |
177 public TextStyle [] getStyles () { | |
178 checkWidget (); | |
179 if (styles is null) return new TextStyle [0]; | |
180 TextStyle [] result = new TextStyle [styles.length]; | |
181 System.arraycopy (styles, 0, result, 0, styles.length); | |
182 return result; | |
183 } | |
184 | |
185 public String getText () { | |
186 checkWidget (); | |
187 return text; | |
188 } | |
189 | |
190 public bool getWideCaret() { | |
191 checkWidget (); | |
192 auto layout = OS.GetKeyboardLayout (0); | |
193 short langID = cast(short)OS.LOWORD ( cast(int) layout); | |
194 return OS.PRIMARYLANGID (langID) is OS.LANG_KOREAN; | |
195 } | |
196 | |
197 bool isInlineEnabled () { | |
198 if (OS.IsWinCE || OS.WIN32_VERSION < OS.VERSION (5, 1)) return false; | |
199 return OS.IsDBLocale && hooks (DWT.ImeComposition); | |
200 } | |
201 | |
202 void releaseParent () { | |
203 super.releaseParent (); | |
204 if (this is parent.getIME ()) parent.setIME (null); | |
205 } | |
206 | |
207 void releaseWidget () { | |
208 super.releaseWidget (); | |
209 parent = null; | |
210 text = null; | |
211 styles = null; | |
212 ranges = null; | |
213 } | |
214 | |
215 public void setCompositionOffset (int offset) { | |
216 checkWidget (); | |
217 if (offset < 0) return; | |
218 if (startOffset !is -1) { | |
219 startOffset = offset; | |
220 } | |
221 } | |
222 | |
223 LRESULT WM_IME_COMPOSITION (int /*long*/ wParam, int /*long*/ lParam) { | |
224 if (!isInlineEnabled ()) return null; | |
225 ranges = null; | |
226 styles = null; | |
227 caretOffset = commitCount = 0; | |
228 auto hwnd = parent.handle; | |
229 auto hIMC = OS.ImmGetContext (hwnd); | |
230 int codePage = parent.getCodePage (); | |
231 if (hIMC !is null) { | |
232 TCHAR[] buffer = null; | |
233 if ((lParam & OS.GCS_RESULTSTR) !is 0) { | |
234 int length_ = OS.ImmGetCompositionString (hIMC, OS.GCS_RESULTSTR, null, 0); | |
235 if (length_ > 0) { | |
236 buffer = NewTCHARs (codePage, length_ / TCHAR.sizeof); | |
237 OS.ImmGetCompositionString (hIMC, OS.GCS_RESULTSTR, buffer.ptr, length_); | |
238 if (startOffset is -1) { | |
239 Event event = new Event (); | |
240 event.detail = DWT.COMPOSITION_SELECTION; | |
241 sendEvent (DWT.ImeComposition, event); | |
242 startOffset = event.start; | |
243 } | |
244 Event event = new Event (); | |
245 event.detail = DWT.COMPOSITION_CHANGED; | |
246 event.start = startOffset; | |
247 event.end = startOffset + text.length; | |
248 event.text = text = buffer !is null ? TCHARsToStr(buffer) : ""; | |
249 commitCount = text.length ; | |
250 sendEvent (DWT.ImeComposition, event); | |
251 String chars = text; | |
252 text = ""; | |
253 startOffset = -1; | |
254 commitCount = 0; | |
255 if (event.doit) { | |
256 Display display = this.display; | |
257 display.lastKey = 0; | |
258 display.lastVirtual = display.lastNull = display.lastDead = false; | |
259 length_ = chars.length; | |
260 for (int i = 0; i < length_; i++) { | |
261 char c = chars.charAt (i); | |
262 display.lastAscii = c; | |
263 event = new Event (); | |
264 event.character = c; | |
265 parent.sendEvent (DWT.KeyDown, event); | |
266 } | |
267 } | |
268 } | |
269 if ((lParam & OS.GCS_COMPSTR) is 0) return LRESULT.ONE; | |
270 } | |
271 buffer = null; | |
272 if ((lParam & OS.GCS_COMPSTR) !is 0) { | |
273 int length_ = OS.ImmGetCompositionString (hIMC, OS.GCS_COMPSTR, null, 0); | |
274 if (length_ > 0) { | |
275 buffer = NewTCHARs (codePage, length_ / TCHAR.sizeof); | |
276 OS.ImmGetCompositionString (hIMC, OS.GCS_COMPSTR, buffer.ptr, length_); | |
277 if ((lParam & OS.GCS_CURSORPOS) !is 0) { | |
278 caretOffset = OS.ImmGetCompositionString (hIMC, OS.GCS_CURSORPOS, null, 0); | |
279 } | |
280 int [] clauses = null; | |
281 if ((lParam & OS.GCS_COMPCLAUSE) !is 0) { | |
282 length_ = OS.ImmGetCompositionStringW (hIMC, OS.GCS_COMPCLAUSE, /+cast(int [])+/null, 0); | |
283 if (length_ > 0) { | |
284 clauses = new int [length_ / 4]; | |
285 OS.ImmGetCompositionStringW (hIMC, OS.GCS_COMPCLAUSE, clauses.ptr, length_); | |
286 } | |
287 } | |
288 if ((lParam & OS.GCS_COMPATTR) !is 0 && clauses !is null) { | |
289 length_ = OS.ImmGetCompositionStringA (hIMC, OS.GCS_COMPATTR, /+cast(byte [])+/null, 0); | |
290 if (length_ > 0) { | |
291 byte [] attrs = new byte [length_]; | |
292 OS.ImmGetCompositionStringA (hIMC, OS.GCS_COMPATTR, attrs.ptr, length_); | |
293 length_ = clauses.length - 1; | |
294 ranges = new int [length_ * 2]; | |
295 styles = new TextStyle [length_]; | |
296 auto layout = OS.GetKeyboardLayout (0); | |
297 short langID = cast(short)OS.LOWORD ( cast(int) layout); | |
298 TF_DISPLAYATTRIBUTE* attr = null; | |
299 TextStyle style = null; | |
300 for (int i = 0; i < length_; i++) { | |
301 ranges [i * 2] = clauses [i]; | |
302 ranges [i * 2 + 1] = clauses [i + 1] - 1; | |
303 styles [i] = style = new TextStyle (); | |
304 attr = getDisplayAttribute (langID, attrs [clauses [i]]); | |
305 if (attr !is null) { | |
306 switch (attr.crText.type) { | |
307 case OS.TF_CT_COLORREF: | |
308 style.foreground = Color.win32_new (display, attr.crText.cr); | |
309 break; | |
310 case OS.TF_CT_SYSCOLOR: | |
311 int colorRef = OS.GetSysColor (attr.crText.cr); | |
312 style.foreground = Color.win32_new (display, colorRef); | |
313 break; | |
314 } | |
315 switch (attr.crBk.type) { | |
316 case OS.TF_CT_COLORREF: | |
317 style.background = Color.win32_new (display, attr.crBk.cr); | |
318 break; | |
319 case OS.TF_CT_SYSCOLOR: | |
320 int colorRef = OS.GetSysColor (attr.crBk.cr); | |
321 style.background = Color.win32_new (display, colorRef); | |
322 break; | |
323 } | |
324 switch (attr.crLine.type) { | |
325 case OS.TF_CT_COLORREF: | |
326 style.underlineColor = Color.win32_new (display, attr.crLine.cr); | |
327 break; | |
328 case OS.TF_CT_SYSCOLOR: | |
329 int colorRef = OS.GetSysColor (attr.crLine.cr); | |
330 style.underlineColor = Color.win32_new (display, colorRef); | |
331 break; | |
332 } | |
333 style.underline = attr.lsStyle !is OS.TF_LS_NONE; | |
334 switch (attr.lsStyle) { | |
335 case OS.TF_LS_SQUIGGLE: | |
336 style.underlineStyle = DWT.UNDERLINE_SQUIGGLE; | |
337 break; | |
338 case OS.TF_LS_DASH: | |
339 style.underlineStyle = UNDERLINE_IME_DASH; | |
340 break; | |
341 case OS.TF_LS_DOT: | |
342 style.underlineStyle = UNDERLINE_IME_DOT; | |
343 break; | |
344 case OS.TF_LS_SOLID: | |
345 style.underlineStyle = attr.fBoldLine ? UNDERLINE_IME_THICK : DWT.UNDERLINE_SINGLE; | |
346 break; | |
347 } | |
348 } | |
349 } | |
350 } | |
351 } | |
352 } | |
353 OS.ImmReleaseContext (hwnd, hIMC); | |
354 } | |
355 int end = startOffset + text.length; | |
356 if (startOffset is -1) { | |
357 Event event = new Event (); | |
358 event.detail = DWT.COMPOSITION_SELECTION; | |
359 sendEvent (DWT.ImeComposition, event); | |
360 startOffset = event.start; | |
361 end = event.end; | |
362 } | |
363 Event event = new Event (); | |
364 event.detail = DWT.COMPOSITION_CHANGED; | |
365 event.start = startOffset; | |
366 event.end = end; | |
367 event.text = text = buffer !is null ? TCHARsToStr(buffer) : ""; | |
368 sendEvent (DWT.ImeComposition, event); | |
369 if (text.length is 0) { | |
370 startOffset = -1; | |
371 ranges = null; | |
372 styles = null; | |
373 } | |
374 } | |
375 return LRESULT.ONE; | |
376 } | |
377 | |
378 LRESULT WM_IME_COMPOSITION_START (int /*long*/ wParam, int /*long*/ lParam) { | |
379 return isInlineEnabled () ? LRESULT.ONE : null; | |
380 } | |
381 | |
382 LRESULT WM_IME_ENDCOMPOSITION (int /*long*/ wParam, int /*long*/ lParam) { | |
383 return isInlineEnabled () ? LRESULT.ONE : null; | |
384 } | |
385 | |
386 LRESULT WM_KILLFOCUS (int /*long*/ wParam, int /*long*/ lParam) { | |
387 if (!isInlineEnabled ()) return null; | |
388 auto hwnd = parent.handle; | |
389 auto hIMC = OS.ImmGetContext (hwnd); | |
390 if (hIMC !is null) { | |
391 if (OS.ImmGetOpenStatus (hIMC)) { | |
392 OS.ImmNotifyIME (hIMC, OS.NI_COMPOSITIONSTR, OS.CPS_COMPLETE, 0); | |
393 } | |
394 OS.ImmReleaseContext (hwnd, hIMC); | |
395 } | |
396 return null; | |
397 } | |
398 | |
399 LRESULT WM_LBUTTONDOWN (int /*long*/ wParam, int /*long*/ lParam) { | |
400 if (!isInlineEnabled ()) return null; | |
401 auto hwnd = parent.handle; | |
402 auto hIMC = OS.ImmGetContext (hwnd); | |
403 if (hIMC !is null) { | |
404 if (OS.ImmGetOpenStatus (hIMC)) { | |
405 if (OS.ImmGetCompositionString (hIMC, OS.GCS_COMPSTR, null, 0) > 0) { | |
406 Event event = new Event (); | |
407 event.detail = DWT.COMPOSITION_OFFSET; | |
408 event.x = OS.GET_X_LPARAM (lParam); | |
409 event.y = OS.GET_Y_LPARAM (lParam); | |
410 sendEvent (DWT.ImeComposition, event); | |
411 int offset = event.index; | |
412 int length_ = text.length; | |
413 if (offset !is -1 && startOffset !is -1 && startOffset <= offset && offset < startOffset + length_) { | |
414 auto imeWnd = OS.ImmGetDefaultIMEWnd (hwnd); | |
415 offset = event.index + event.count - startOffset; | |
416 int trailing = event.count > 0 ? 1 : 2; | |
417 int /*long*/ param = OS.MAKEWPARAM (OS.MAKEWORD (OS.IMEMOUSE_LDOWN, trailing), offset); | |
418 OS.SendMessage (imeWnd, WM_MSIME_MOUSE, param, hIMC); | |
419 } else { | |
420 OS.ImmNotifyIME (hIMC, OS.NI_COMPOSITIONSTR, OS.CPS_COMPLETE, 0); | |
421 } | |
422 } | |
423 } | |
424 OS.ImmReleaseContext (hwnd, hIMC); | |
425 } | |
426 return null; | |
427 } | |
428 | |
429 } |