Mercurial > projects > dwt-win
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/widgets/IME.d Sat May 17 17:34:28 2008 +0200 @@ -0,0 +1,429 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +module dwt.widgets.IME; + + +import dwt.DWT; +import dwt.graphics.Color; +import dwt.graphics.TextStyle; +import dwt.internal.win32.OS; +import dwt.internal.win32.WINTYPES; + +import dwt.widgets.Widget; +import dwt.widgets.Canvas; +import dwt.widgets.Event; +import dwt.widgets.Display; + +import dwt.dwthelper.utils; + +/** + * TODO - JAVA DOC + * + * <dl> + * <dt><b>Styles:</b></dt> + * <dd>(none)</dd> + * <dt><b>Events:</b></dt> + * <dd>(none)</dd> + * </dl> + * <p> + * . + * </p> + * + * @since 3.4 + */ + +public class IME : Widget { + Canvas parent; + int caretOffset; + int startOffset; + int commitCount; + String text; + int [] ranges; + TextStyle [] styles; + + static const int WM_MSIME_MOUSE; + + static byte [16] IID_ITfInputProcessorProfiles; + static byte [16] IID_ITfDisplayAttributeProvider; + static byte [16] CLSID_TF_InputProcessorProfiles; + static byte [16] GUID_TFCAT_TIP_KEYBOARD; + static this() { + WM_MSIME_MOUSE = OS.RegisterWindowMessage (StrToTCHARz ("MSIMEMouseOperation")); + + OS.IIDFromString ("{1F02B6C5-7842-4EE6-8A0B-9A24183A95CA}\0"w.ptr, IID_ITfInputProcessorProfiles.ptr); + OS.IIDFromString ("{fee47777-163c-4769-996a-6e9c50ad8f54}\0"w.ptr, IID_ITfDisplayAttributeProvider.ptr); + OS.IIDFromString ("{33C53A50-F456-4884-B049-85FD643ECFED}\0"w.ptr, CLSID_TF_InputProcessorProfiles.ptr); + OS.IIDFromString ("{34745C63-B2F0-4784-8B67-5E12C8701A31}\0"w.ptr, GUID_TFCAT_TIP_KEYBOARD.ptr); + } + + /* TextLayout has a copy of these constants */ + static const int UNDERLINE_IME_DOT = 1 << 16; + static const int UNDERLINE_IME_DASH = 2 << 16; + static const int UNDERLINE_IME_THICK = 3 << 16; + +/** + * Prevents uninitialized instances from being created outside the package. + */ +this () { +} + +/** + * + * @see DWT + */ +public this (Canvas parent, int style) { + super (parent, style); + this.parent = parent; + createWidget (); +} + +void createWidget () { + text = ""; + startOffset = -1; + if (parent.getIME () is null) { + parent.setIME (this); + } +} + +public int getCaretOffset () { + checkWidget (); + return startOffset + caretOffset; +} + +public int getCommitCount () { + checkWidget (); + return commitCount; +} + +public int getCompositionOffset () { + checkWidget (); + return startOffset; +} + +TF_DISPLAYATTRIBUTE* getDisplayAttribute (short langid, int attInfo) { + void* pProfiles; + int hr = OS.CoCreateInstance (CLSID_TF_InputProcessorProfiles.ptr, null, OS.CLSCTX_INPROC_SERVER, IID_ITfInputProcessorProfiles.ptr, &pProfiles); + TF_DISPLAYATTRIBUTE* pda; + if (hr is OS.S_OK) { + byte [16] pclsid; + byte [16] pguidProfile; + /* pProfiles.GetDefaultLanguageProfile () */ + hr = OS.VtblCall (8, pProfiles, cast(int)langid, cast(int)GUID_TFCAT_TIP_KEYBOARD.ptr, cast(int)pclsid.ptr, cast(int)pguidProfile.ptr); + if (hr is OS.S_OK) { + void* pProvider; + hr = OS.CoCreateInstance (pclsid.ptr, null, OS.CLSCTX_INPROC_SERVER, IID_ITfDisplayAttributeProvider.ptr, &pProvider); + if (hr is OS.S_OK) { + void* pEnum; + /* pProvider.EnumDisplayAttributeInfo () */ + hr = OS.VtblCall (3, pProvider, cast(int)&pEnum); + if (hr is OS.S_OK) { + void* pDispInfo; + TF_DISPLAYATTRIBUTE* tempPda; + /* pEnum.Next () */ + while ((hr = OS.VtblCall (4, pEnum, 1, cast(int) &pDispInfo, 0 )) is OS.S_OK) { + /* pDispInfo.GetAttributeInfo(); */ + OS.VtblCall (5, pDispInfo, cast(int)&tempPda); + /* pDispInfo.Release () */ + OS.VtblCall (2, pDispInfo); + if (tempPda.bAttr is attInfo) { + pda = tempPda; + break; + } + } + /* pEnum.Release () */ + hr = OS.VtblCall (2, pEnum); + } + /* pProvider.Release () */ + hr = OS.VtblCall (2, pProvider); + } + } + /* pProfiles.Release () */ + hr = OS.VtblCall (2, pProfiles); + } + if (pda is null) { + pda = new TF_DISPLAYATTRIBUTE (); + switch (attInfo) { + case OS.TF_ATTR_INPUT: + pda.lsStyle = OS.TF_LS_SQUIGGLE; + break; + case OS.TF_ATTR_CONVERTED: + case OS.TF_ATTR_TARGET_CONVERTED: + pda.lsStyle = OS.TF_LS_SOLID; + pda.fBoldLine = attInfo is OS.TF_ATTR_TARGET_CONVERTED; + break; + } + } + return pda; +} + +public int [] getRanges () { + checkWidget (); + if (ranges is null) return new int [0]; + int [] result = new int [ranges.length]; + for (int i = 0; i < result.length; i++) { + result [i] = ranges [i] + startOffset; + } + return result; +} + +public TextStyle [] getStyles () { + checkWidget (); + if (styles is null) return new TextStyle [0]; + TextStyle [] result = new TextStyle [styles.length]; + System.arraycopy (styles, 0, result, 0, styles.length); + return result; +} + +public String getText () { + checkWidget (); + return text; +} + +public bool getWideCaret() { + checkWidget (); + auto layout = OS.GetKeyboardLayout (0); + short langID = cast(short)OS.LOWORD ( cast(int) layout); + return OS.PRIMARYLANGID (langID) is OS.LANG_KOREAN; +} + +bool isInlineEnabled () { + if (OS.IsWinCE || OS.WIN32_VERSION < OS.VERSION (5, 1)) return false; + return OS.IsDBLocale && hooks (DWT.ImeComposition); +} + +void releaseParent () { + super.releaseParent (); + if (this is parent.getIME ()) parent.setIME (null); +} + +void releaseWidget () { + super.releaseWidget (); + parent = null; + text = null; + styles = null; + ranges = null; +} + +public void setCompositionOffset (int offset) { + checkWidget (); + if (offset < 0) return; + if (startOffset !is -1) { + startOffset = offset; + } +} + +LRESULT WM_IME_COMPOSITION (int /*long*/ wParam, int /*long*/ lParam) { + if (!isInlineEnabled ()) return null; + ranges = null; + styles = null; + caretOffset = commitCount = 0; + auto hwnd = parent.handle; + auto hIMC = OS.ImmGetContext (hwnd); + int codePage = parent.getCodePage (); + if (hIMC !is null) { + TCHAR[] buffer = null; + if ((lParam & OS.GCS_RESULTSTR) !is 0) { + int length_ = OS.ImmGetCompositionString (hIMC, OS.GCS_RESULTSTR, null, 0); + if (length_ > 0) { + buffer = NewTCHARs (codePage, length_ / TCHAR.sizeof); + OS.ImmGetCompositionString (hIMC, OS.GCS_RESULTSTR, buffer.ptr, length_); + if (startOffset is -1) { + Event event = new Event (); + event.detail = DWT.COMPOSITION_SELECTION; + sendEvent (DWT.ImeComposition, event); + startOffset = event.start; + } + Event event = new Event (); + event.detail = DWT.COMPOSITION_CHANGED; + event.start = startOffset; + event.end = startOffset + text.length; + event.text = text = buffer !is null ? TCHARsToStr(buffer) : ""; + commitCount = text.length ; + sendEvent (DWT.ImeComposition, event); + String chars = text; + text = ""; + startOffset = -1; + commitCount = 0; + if (event.doit) { + Display display = this.display; + display.lastKey = 0; + display.lastVirtual = display.lastNull = display.lastDead = false; + length_ = chars.length; + for (int i = 0; i < length_; i++) { + char c = chars.charAt (i); + display.lastAscii = c; + event = new Event (); + event.character = c; + parent.sendEvent (DWT.KeyDown, event); + } + } + } + if ((lParam & OS.GCS_COMPSTR) is 0) return LRESULT.ONE; + } + buffer = null; + if ((lParam & OS.GCS_COMPSTR) !is 0) { + int length_ = OS.ImmGetCompositionString (hIMC, OS.GCS_COMPSTR, null, 0); + if (length_ > 0) { + buffer = NewTCHARs (codePage, length_ / TCHAR.sizeof); + OS.ImmGetCompositionString (hIMC, OS.GCS_COMPSTR, buffer.ptr, length_); + if ((lParam & OS.GCS_CURSORPOS) !is 0) { + caretOffset = OS.ImmGetCompositionString (hIMC, OS.GCS_CURSORPOS, null, 0); + } + int [] clauses = null; + if ((lParam & OS.GCS_COMPCLAUSE) !is 0) { + length_ = OS.ImmGetCompositionStringW (hIMC, OS.GCS_COMPCLAUSE, /+cast(int [])+/null, 0); + if (length_ > 0) { + clauses = new int [length_ / 4]; + OS.ImmGetCompositionStringW (hIMC, OS.GCS_COMPCLAUSE, clauses.ptr, length_); + } + } + if ((lParam & OS.GCS_COMPATTR) !is 0 && clauses !is null) { + length_ = OS.ImmGetCompositionStringA (hIMC, OS.GCS_COMPATTR, /+cast(byte [])+/null, 0); + if (length_ > 0) { + byte [] attrs = new byte [length_]; + OS.ImmGetCompositionStringA (hIMC, OS.GCS_COMPATTR, attrs.ptr, length_); + length_ = clauses.length - 1; + ranges = new int [length_ * 2]; + styles = new TextStyle [length_]; + auto layout = OS.GetKeyboardLayout (0); + short langID = cast(short)OS.LOWORD ( cast(int) layout); + TF_DISPLAYATTRIBUTE* attr = null; + TextStyle style = null; + for (int i = 0; i < length_; i++) { + ranges [i * 2] = clauses [i]; + ranges [i * 2 + 1] = clauses [i + 1] - 1; + styles [i] = style = new TextStyle (); + attr = getDisplayAttribute (langID, attrs [clauses [i]]); + if (attr !is null) { + switch (attr.crText.type) { + case OS.TF_CT_COLORREF: + style.foreground = Color.win32_new (display, attr.crText.cr); + break; + case OS.TF_CT_SYSCOLOR: + int colorRef = OS.GetSysColor (attr.crText.cr); + style.foreground = Color.win32_new (display, colorRef); + break; + } + switch (attr.crBk.type) { + case OS.TF_CT_COLORREF: + style.background = Color.win32_new (display, attr.crBk.cr); + break; + case OS.TF_CT_SYSCOLOR: + int colorRef = OS.GetSysColor (attr.crBk.cr); + style.background = Color.win32_new (display, colorRef); + break; + } + switch (attr.crLine.type) { + case OS.TF_CT_COLORREF: + style.underlineColor = Color.win32_new (display, attr.crLine.cr); + break; + case OS.TF_CT_SYSCOLOR: + int colorRef = OS.GetSysColor (attr.crLine.cr); + style.underlineColor = Color.win32_new (display, colorRef); + break; + } + style.underline = attr.lsStyle !is OS.TF_LS_NONE; + switch (attr.lsStyle) { + case OS.TF_LS_SQUIGGLE: + style.underlineStyle = DWT.UNDERLINE_SQUIGGLE; + break; + case OS.TF_LS_DASH: + style.underlineStyle = UNDERLINE_IME_DASH; + break; + case OS.TF_LS_DOT: + style.underlineStyle = UNDERLINE_IME_DOT; + break; + case OS.TF_LS_SOLID: + style.underlineStyle = attr.fBoldLine ? UNDERLINE_IME_THICK : DWT.UNDERLINE_SINGLE; + break; + } + } + } + } + } + } + OS.ImmReleaseContext (hwnd, hIMC); + } + int end = startOffset + text.length; + if (startOffset is -1) { + Event event = new Event (); + event.detail = DWT.COMPOSITION_SELECTION; + sendEvent (DWT.ImeComposition, event); + startOffset = event.start; + end = event.end; + } + Event event = new Event (); + event.detail = DWT.COMPOSITION_CHANGED; + event.start = startOffset; + event.end = end; + event.text = text = buffer !is null ? TCHARsToStr(buffer) : ""; + sendEvent (DWT.ImeComposition, event); + if (text.length is 0) { + startOffset = -1; + ranges = null; + styles = null; + } + } + return LRESULT.ONE; +} + +LRESULT WM_IME_COMPOSITION_START (int /*long*/ wParam, int /*long*/ lParam) { + return isInlineEnabled () ? LRESULT.ONE : null; +} + +LRESULT WM_IME_ENDCOMPOSITION (int /*long*/ wParam, int /*long*/ lParam) { + return isInlineEnabled () ? LRESULT.ONE : null; +} + +LRESULT WM_KILLFOCUS (int /*long*/ wParam, int /*long*/ lParam) { + if (!isInlineEnabled ()) return null; + auto hwnd = parent.handle; + auto hIMC = OS.ImmGetContext (hwnd); + if (hIMC !is null) { + if (OS.ImmGetOpenStatus (hIMC)) { + OS.ImmNotifyIME (hIMC, OS.NI_COMPOSITIONSTR, OS.CPS_COMPLETE, 0); + } + OS.ImmReleaseContext (hwnd, hIMC); + } + return null; +} + +LRESULT WM_LBUTTONDOWN (int /*long*/ wParam, int /*long*/ lParam) { + if (!isInlineEnabled ()) return null; + auto hwnd = parent.handle; + auto hIMC = OS.ImmGetContext (hwnd); + if (hIMC !is null) { + if (OS.ImmGetOpenStatus (hIMC)) { + if (OS.ImmGetCompositionString (hIMC, OS.GCS_COMPSTR, null, 0) > 0) { + Event event = new Event (); + event.detail = DWT.COMPOSITION_OFFSET; + event.x = OS.GET_X_LPARAM (lParam); + event.y = OS.GET_Y_LPARAM (lParam); + sendEvent (DWT.ImeComposition, event); + int offset = event.index; + int length_ = text.length; + if (offset !is -1 && startOffset !is -1 && startOffset <= offset && offset < startOffset + length_) { + auto imeWnd = OS.ImmGetDefaultIMEWnd (hwnd); + offset = event.index + event.count - startOffset; + int trailing = event.count > 0 ? 1 : 2; + int /*long*/ param = OS.MAKEWPARAM (OS.MAKEWORD (OS.IMEMOUSE_LDOWN, trailing), offset); + OS.SendMessage (imeWnd, WM_MSIME_MOUSE, param, hIMC); + } else { + OS.ImmNotifyIME (hIMC, OS.NI_COMPOSITIONSTR, OS.CPS_COMPLETE, 0); + } + } + } + OS.ImmReleaseContext (hwnd, hIMC); + } + return null; +} + +}