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 }