diff options
8 files changed, 567 insertions, 444 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java index 2f07882a01..8a1f6dcf00 100755 --- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java @@ -150,7 +150,7 @@ public class StyledText extends Canvas { boolean updateCaretDirection = true; boolean fixedLineHeight; boolean dragDetect = true; - int compositionStart = -1, compositionLength; + IME ime; int alignment; boolean justify; @@ -1210,7 +1210,8 @@ public StyledText(Composite parent, int style) { renderer = new StyledTextRenderer(getDisplay(), this); renderer.setContent(content); renderer.setFont(getFont(), tabLength); - defaultCaret = new Caret(this, SWT.NULL); + ime = new IME(this, SWT.NONE); + defaultCaret = new Caret(this, SWT.NONE); if ((style & SWT.WRAP) != 0) { setWordWrap(true); } @@ -4621,7 +4622,7 @@ int getVisualLineIndex(TextLayout layout, int offsetInLine) { } int getCaretDirection() { if (!isBidiCaret()) return SWT.DEFAULT; - if (compositionStart != -1 && compositionLength > 0) return SWT.DEFAULT; + if (ime.getCompositionOffset() != -1) return SWT.DEFAULT; if (!updateCaretDirection && caretDirection != SWT.NULL) return caretDirection; updateCaretDirection = false; int caretLine = getCaretLine(); @@ -4809,7 +4810,6 @@ void installListeners() { public void handleEvent(Event event) { switch (event.type) { case SWT.Dispose: handleDispose(event); break; - case SWT.ImeComposition: handleImeComposition(event); break; case SWT.KeyDown: handleKeyDown(event); break; case SWT.KeyUp: handleKeyUp(event); break; case SWT.MouseDown: handleMouseDown(event); break; @@ -4822,7 +4822,6 @@ void installListeners() { } }; addListener(SWT.Dispose, listener); - addListener(SWT.ImeComposition, listener); addListener(SWT.KeyDown, listener); addListener(SWT.KeyUp, listener); addListener(SWT.MouseDown, listener); @@ -4831,6 +4830,11 @@ void installListeners() { addListener(SWT.Paint, listener); addListener(SWT.Resize, listener); addListener(SWT.Traverse, listener); + ime.addListener(SWT.ImeComposition, new Listener() { + public void handleEvent(Event event) { + handleImeComposition(event); + } + }); if (verticalBar != null) { verticalBar.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { @@ -4936,49 +4940,26 @@ void internalRedrawRange(int start, int length) { } void handleCompositionHittest (Event event) { int[] trailing = new int [1]; - int offset = getOffsetAtPoint(event.x, event.y, trailing, true); - if (offset != -1) { - if (compositionStart <= offset && offset < compositionStart + compositionLength) { - event.hitTest = SWT.HITTEST_INSIDE_COMPOSITION; - event.index = offset - compositionStart; - } else { - event.hitTest = SWT.HITTEST_INSIDE_TEXT; - event.index = offset; - } - event.trailing = trailing[0]; - } else { - event.hitTest = SWT.HITTEST_OUTSIDE_TEXT; - } + event.index = getOffsetAtPoint(event.x, event.y, trailing, true); + event.count = trailing[0]; } void handleCompositionChanged(Event event) { String text = event.text; + int start = event.start; int length = text.length(); - if (compositionStart == -1) { - compositionStart = caretOffset; - compositionLength = 0; - } - int oldLength = compositionLength; - compositionLength = 0; - renderer.imeRanges = null; - renderer.imeStyles = null; - if (length == event.count) { - content.replaceTextRange(compositionStart, oldLength, ""); - caretOffset = compositionStart; - compositionStart = -1; + if (length == ime.getCommitCount()) { + content.replaceTextRange(start, event.end - start, ""); + caretOffset = start; caretWidth = 0; caretDirection = SWT.NULL; } else { - content.replaceTextRange(compositionStart, oldLength, text); - compositionLength = length; - caretOffset = compositionStart + event.index; - int lineIndex = getCaretLine(); - renderer.imeRanges = event.ranges; - renderer.imeStyles = event.styles; - resetCache(lineIndex, 1); - if (event.wideCaret) { + content.replaceTextRange(start, event.end - start, text); + caretOffset = ime.getCaretOffset(); + if (ime.getWideCaret()) { + int lineIndex = getCaretLine(); int lineOffset = content.getOffsetAtLine(lineIndex); TextLayout layout = renderer.getTextLayout(lineIndex); - caretWidth = layout.getBounds(compositionStart - lineOffset, compositionStart + compositionLength - 1 - lineOffset).width; + caretWidth = layout.getBounds(start - lineOffset, start + length - 1 - lineOffset).width; renderer.disposeTextLayout(layout); } } @@ -4987,7 +4968,7 @@ void handleCompositionChanged(Event event) { void handleImeComposition (Event event) { switch (event.detail) { case SWT.COMPOSITION_CHANGED: handleCompositionChanged(event); break; - case SWT.COMPOSITION_HITTEST: handleCompositionHittest(event); break; + case SWT.COMPOSITION_OFFSET: handleCompositionHittest(event); break; } } /** @@ -6768,6 +6749,7 @@ void setCaretLocation(Point location, int direction) { BidiUtil.setKeyboardLanguage(BidiUtil.KEYBOARD_BIDI); } } + caret.setOffset(caretOffset); } columnX = location.x; } diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextRenderer.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextRenderer.java index a5f7e5c40e..62c1942021 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextRenderer.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledTextRenderer.java @@ -54,10 +54,6 @@ class StyledTextRenderer { int stylesSetCount = 0; final static int BULLET_MARGIN = 8; - /* IME styles*/ - int[] imeRanges; - TextStyle[] imeStyles; - final static boolean COMPACT_STYLES = true; final static boolean MERGE_STYLES = true; @@ -839,45 +835,51 @@ TextLayout getTextLayout(int lineIndex, int orientation, int width, int lineSpac } } if (lastOffset < length) layout.setStyle(null, lastOffset, length); - if (styledText != null) { - int compositionStart = styledText.compositionStart; - int compositionLength = styledText.compositionLength; - if (compositionStart != -1 && compositionLength > 0) { - int compositionLine = content.getLineAtOffset(compositionStart); - if (compositionLine == lineIndex) { - if (imeRanges != null && imeStyles != null) { - for (int i = 0; i < imeStyles.length; i++) { - int start = imeRanges[i*2] + compositionStart - lineOffset; - int end = start + imeRanges[i*2+1] - 1; - TextStyle imeStyle = imeStyles[i], userStyle; - for (int j = start; j <= end; j++) { - userStyle = layout.getStyle(j); - if (userStyle == null && j > 0) userStyle = layout.getStyle(j - 1); - if (userStyle == null && j + 1 < length) userStyle = layout.getStyle(j + 1); - if (userStyle == null) { - layout.setStyle(imeStyle, j, j); - } else { - TextStyle newStyle = new TextStyle(imeStyle); - if (newStyle.font == null) newStyle.font = userStyle.font; - if (newStyle.foreground == null) newStyle.foreground = userStyle.foreground; - if (newStyle.background == null) newStyle.background = userStyle.background; - layout.setStyle(newStyle, j, j); + if (styledText != null && styledText.ime != null) { + IME ime = styledText.ime; + int compositionOffset = ime.getCompositionOffset(); + if (compositionOffset != -1) { + int commitCount = ime.getCommitCount(); + int compositionLength = ime.getText().length(); + if (compositionLength != commitCount) { + int compositionLine = content.getLineAtOffset(compositionOffset); + if (compositionLine == lineIndex) { + int[] imeRanges = ime.getRanges(); + TextStyle[] imeStyles = ime.getStyles(); + if (imeRanges.length > 0) { + for (int i = 0; i < imeStyles.length; i++) { + int start = imeRanges[i*2] + compositionOffset - lineOffset; + int end = start + imeRanges[i*2+1] - 1; + TextStyle imeStyle = imeStyles[i], userStyle; + for (int j = start; j <= end; j++) { + userStyle = layout.getStyle(j); + if (userStyle == null && j > 0) userStyle = layout.getStyle(j - 1); + if (userStyle == null && j + 1 < length) userStyle = layout.getStyle(j + 1); + if (userStyle == null) { + layout.setStyle(imeStyle, j, j); + } else { + TextStyle newStyle = new TextStyle(imeStyle); + if (newStyle.font == null) newStyle.font = userStyle.font; + if (newStyle.foreground == null) newStyle.foreground = userStyle.foreground; + if (newStyle.background == null) newStyle.background = userStyle.background; + layout.setStyle(newStyle, j, j); + } } } - } - } else { - int start = compositionStart - lineOffset; - int end = start + compositionLength - 1; - TextStyle userStyle = layout.getStyle(start); - if (userStyle == null) { - if (start > 0) userStyle = layout.getStyle(start - 1); - if (userStyle == null && end + 1 < length) userStyle = layout.getStyle(end + 1); - if (userStyle != null) { - TextStyle newStyle = new TextStyle(); - newStyle.font = userStyle.font; - newStyle.foreground = userStyle.foreground; - newStyle.background = userStyle.background; - layout.setStyle(newStyle, start, end); + } else { + int start = compositionOffset - lineOffset; + int end = start + compositionLength - 1; + TextStyle userStyle = layout.getStyle(start); + if (userStyle == null) { + if (start > 0) userStyle = layout.getStyle(start - 1); + if (userStyle == null && end + 1 < length) userStyle = layout.getStyle(end + 1); + if (userStyle != null) { + TextStyle newStyle = new TextStyle(); + newStyle.font = userStyle.font; + newStyle.foreground = userStyle.foreground; + newStyle.background = userStyle.background; + layout.setStyle(newStyle, start, end); + } } } } @@ -949,8 +951,6 @@ void reset() { bullets = null; bulletsIndices = null; redrawLines = null; - imeRanges = null; - imeStyles = null; } void reset(int startLine, int lineCount) { int endLine = startLine + lineCount; diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/SWT.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/SWT.java index dd74d39278..4e8d9eb725 100755 --- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/SWT.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/SWT.java @@ -622,7 +622,7 @@ public class SWT { * The detail field indicates the action to be taken: * <p><ul> * <li>{@link SWT#COMPOSITION_CHANGED}</li> - * <li>{@link SWT#COMPOSITION_HITTEST}</li> + * <li>{@link SWT#COMPOSITION_OFFSET}</li> * </ul></p> * * @see org.eclipse.swt.widgets.Widget#addListener @@ -674,42 +674,7 @@ public class SWT { * * @since 3.4 */ - public static final int COMPOSITION_HITTEST = 2; - - /** - * Indicates that a hit test has occurred outside of - * the text (value is 1). - * - * @see SWT#COMPOSITION_HITTEST - * @see org.eclipse.swt.widgets.Event#hitTest - * - * @since 3.4 - */ - public static final int HITTEST_OUTSIDE_TEXT = 1; - - - /** - * Indicates that a hit test has occurred inside of - * the text (value is 2). - * - * @see SWT#COMPOSITION_HITTEST - * @see org.eclipse.swt.widgets.Event#hitTest - * - * @since 3.4 - */ - public static final int HITTEST_INSIDE_TEXT = 2; - - /** - * Indicates that a hit test has occurred inside of - * the IME composition text (value is 3). - * - * @see SWT#COMPOSITION_HITTEST - * @see org.eclipse.swt.widgets.Event#hitTest - * - * @since 3.4 - */ - public static final int HITTEST_INSIDE_COMPOSITION = 3; - + public static final int COMPOSITION_OFFSET = 2; /** * Indicates that a user-interface component is being dragged, diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Event.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Event.java index f453a26119..a797fae3fe 100755 --- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Event.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Event.java @@ -173,53 +173,6 @@ public class Event { * be inserted or deleted. */ public String text; - - /** - * the ranges in the text where styles should be applied. - * - * @since 3.4 - */ - public int [] ranges; - - /** - * the styles for the text. - * - * @since 3.4 - */ - public TextStyle [] styles; - - /** - * the hitTest that indicates a part given a x and y location. - * - * @see org.eclipse.swt.SWT#COMPOSITION_HITTEST - * @see org.eclipse.swt.SWT#HITTEST_INSIDE_COMPOSITION - * @see org.eclipse.swt.SWT#HITTEST_INSIDE_TEXT - * @see org.eclipse.swt.SWT#HITTEST_OUTSIDE_TEXT - * - * @since 3.4 - */ - public int hitTest; - - /** - * the trailing specifies if the hit test occurred in the - * leading (0) or trailing edge (1) of the character. - * - * @see org.eclipse.swt.SWT#COMPOSITION_HITTEST - * @see org.eclipse.swt.graphics.TextLayout#getOffset(int, int, int[]) - * - * @since 3.4 - */ - public int trailing; - - /** - * this flag is set by the IME to indicate to the application that - * a wide caret should be use. - * - * @see org.eclipse.swt.SWT#COMPOSITION_CHANGED - * - * @since 3.4 - */ - public boolean wideCaret; /** * depending on the event, a flag indicating whether the operation diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/TextLayout.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/TextLayout.java index 2a69af660b..0fc76c90c3 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/TextLayout.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/TextLayout.java @@ -60,7 +60,7 @@ public final class TextLayout extends Resource { OS.IIDFromString("{DCCFC162-2B38-11d2-B7EC-00C04F8F5D9A}\0".toCharArray(), IID_IMLangFontLink2); } - /* Caret has a copy of these constants */ + /* IME has a copy of these constants */ static final int UNDERLINE_IME_DOT = 1 << 16; static final int UNDERLINE_IME_DASH = 2 << 16; static final int UNDERLINE_IME_THICK = 3 << 16; diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Canvas.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Canvas.java index dd72c098d6..70e5300403 100755 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Canvas.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Canvas.java @@ -37,24 +37,7 @@ import org.eclipse.swt.graphics.*; public class Canvas extends Composite { Caret caret; - - static final int WM_MSIME_MOUSE = OS.RegisterWindowMessage (new TCHAR (0, "MSIMEMouseOperation", true)); - - static final byte [] IID_ITfInputProcessorProfiles = new byte [16]; - static final byte [] IID_ITfDisplayAttributeProvider = new byte [16]; - static final byte [] CLSID_TF_InputProcessorProfiles = new byte [16]; - static final byte [] GUID_TFCAT_TIP_KEYBOARD = new byte [16]; - static { - OS.IIDFromString ("{1F02B6C5-7842-4EE6-8A0B-9A24183A95CA}\0".toCharArray (), IID_ITfInputProcessorProfiles); - OS.IIDFromString ("{fee47777-163c-4769-996a-6e9c50ad8f54}\0".toCharArray (), IID_ITfDisplayAttributeProvider); - OS.IIDFromString ("{33C53A50-F456-4884-B049-85FD643ECFED}\0".toCharArray (), CLSID_TF_InputProcessorProfiles); - OS.IIDFromString ("{34745C63-B2F0-4784-8B67-5E12C8701A31}\0".toCharArray (), GUID_TFCAT_TIP_KEYBOARD); - } - - /* TextLayout has a copy of these constants */ - static final int UNDERLINE_IME_DOT = 1 << 16; - static final int UNDERLINE_IME_DASH = 2 << 16; - static final int UNDERLINE_IME_THICK = 3 << 16; + IME ime; /** * Prevents uninitialized instances from being created outside the package. @@ -127,65 +110,21 @@ public Caret getCaret () { return caret; } -TF_DISPLAYATTRIBUTE getDisplayAttribute (short langid, int attInfo) { - int /*long*/ [] pProfiles = new int /*long*/ [1]; - int hr = OS.CoCreateInstance (CLSID_TF_InputProcessorProfiles, 0, OS.CLSCTX_INPROC_SERVER, IID_ITfInputProcessorProfiles, pProfiles); - TF_DISPLAYATTRIBUTE pda = null; - if (hr == OS.S_OK) { - byte [] pclsid = new byte [16]; - byte [] pguidProfile = new byte [16]; - /* pProfiles.GetDefaultLanguageProfile () */ - hr = OS.VtblCall (8, pProfiles [0], langid, GUID_TFCAT_TIP_KEYBOARD, pclsid, pguidProfile); - if (hr == OS.S_OK) { - int /*long*/ [] pProvider = new int /*long*/ [1]; - hr = OS.CoCreateInstance (pclsid, 0, OS.CLSCTX_INPROC_SERVER, IID_ITfDisplayAttributeProvider, pProvider); - if (hr == OS.S_OK) { - int /*long*/ [] pEnum = new int /*long*/ [1]; - /* pProvider.EnumDisplayAttributeInfo () */ - hr = OS.VtblCall (3, pProvider [0], pEnum); - if (hr == OS.S_OK) { - int /*long*/ [] pDispInfo = new int /*long*/ [1]; - TF_DISPLAYATTRIBUTE tempPda = new TF_DISPLAYATTRIBUTE (); - /* pEnum.Next () */ - while ((hr = OS.VtblCall (4, pEnum [0], 1, pDispInfo, null)) == OS.S_OK) { - /* pDispInfo.GetAttributeInfo(); */ - OS.VtblCall (5, pDispInfo [0], tempPda); - /* pDispInfo.Release () */ - OS.VtblCall (2, pDispInfo [0]); - if (tempPda.bAttr == attInfo) { - pda = tempPda; - break; - } - } - /* pEnum.Release () */ - hr = OS.VtblCall (2, pEnum [0]); - } - /* pProvider.Release () */ - hr = OS.VtblCall (2, pProvider [0]); - } - } - /* pProfiles.Release () */ - hr = OS.VtblCall (2, pProfiles [0]); - } - if (pda == 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 == OS.TF_ATTR_TARGET_CONVERTED; - break; - } - } - return pda; -} - -boolean isInlineIMEEnabled () { - if (OS.IsWinCE || OS.WIN32_VERSION < OS.VERSION (5, 1)) return false; - return OS.IsDBLocale && hooks (SWT.ImeComposition); +/** + * Returns the IME. + * + * @return the IME + * + * @exception SWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * + * @since 3.4 + */ +public IME getIME () { + checkWidget (); + return ime; } void releaseChildren (boolean destroy) { @@ -193,6 +132,10 @@ void releaseChildren (boolean destroy) { caret.release (false); caret = null; } + if (ime != null) { + ime.release (false); + ime = null; + } super.releaseChildren (destroy); } @@ -351,6 +294,27 @@ public void setCaret (Caret caret) { } } +/** + * Sets the receiver's IME. + * + * @param ime the new IME for the receiver, may be null + * + * @exception IllegalArgumentException <ul> + * <li>ERROR_INVALID_ARGUMENT - if the IME has been disposed</li> + * </ul> + * @exception SWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * + * @since 3.4 + */ +public void setIME (IME ime) { + checkWidget (); + if (ime != null && ime.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT); + this.ime = ime; +} + public void setFont (Font font) { checkWidget (); if (caret != null) caret.setFont (font); @@ -371,185 +335,56 @@ int /*long*/ windowProc (int /*long*/ hwnd, int msg, int /*long*/ wParam, int /* } LRESULT WM_IME_COMPOSITION (int /*long*/ wParam, int /*long*/ lParam) { - LRESULT result = super.WM_IME_COMPOSITION (wParam, lParam); - if (isInlineIMEEnabled ()) { - int /*long*/ hIMC = OS.ImmGetContext (handle); - if (hIMC != 0) { - TCHAR buffer = null; - if ((lParam & OS.GCS_RESULTSTR) != 0) { - int length = OS.ImmGetCompositionString (hIMC, OS.GCS_RESULTSTR, null, 0); - if (length > 0) { - buffer = new TCHAR (getCodePage (), length / TCHAR.sizeof); - OS.ImmGetCompositionString (hIMC, OS.GCS_RESULTSTR, buffer, length); - String text = buffer.toString (); - Event event = new Event (); - event.detail = SWT.COMPOSITION_CHANGED; - event.text = text; - event.count = text.length (); - sendEvent (SWT.ImeComposition, event); - if (event.doit) { - Display display = this.display; - display.lastKey = 0; - display.lastVirtual = display.lastNull = display.lastDead = false; - length = text.length (); - for (int i = 0; i < length; i++) { - char c = text.charAt (i); - display.lastAscii = c; - event = new Event (); - event.character = c; - sendEvent (SWT.KeyDown, event); - } - } - } - if ((lParam & OS.GCS_COMPSTR) == 0) return LRESULT.ONE; - } - - buffer = null; - int index = 0; - int [] ranges = null; - TextStyle [] styles = null; - int /*long*/ layout = OS.GetKeyboardLayout (0); - short langID = (short)OS.LOWORD (layout); - if ((lParam & OS.GCS_COMPSTR) != 0) { - int length = OS.ImmGetCompositionString (hIMC, OS.GCS_COMPSTR, null, 0); - if (length > 0) { - buffer = new TCHAR (getCodePage (), length / TCHAR.sizeof); - OS.ImmGetCompositionString (hIMC, OS.GCS_COMPSTR, buffer, length); - if ((lParam & OS.GCS_CURSORPOS) != 0) { - index = OS.ImmGetCompositionString (hIMC, OS.GCS_CURSORPOS, null, 0); - } - int [] clauses = null; - if ((lParam & OS.GCS_COMPCLAUSE) != 0) { - length = OS.ImmGetCompositionStringW (hIMC, OS.GCS_COMPCLAUSE, (int [])null, 0); - if (length > 0) { - clauses = new int [length / 4]; - OS.ImmGetCompositionStringW (hIMC, OS.GCS_COMPCLAUSE, clauses, length); - } - } - if ((lParam & OS.GCS_COMPATTR) != 0 && clauses != null) { - length = OS.ImmGetCompositionStringA (hIMC, OS.GCS_COMPATTR, (byte [])null, 0); - if (length > 0) { - byte [] attrs = new byte [length]; - OS.ImmGetCompositionStringA (hIMC, OS.GCS_COMPATTR, attrs, length); - length = clauses.length - 1; - ranges = new int [length * 2]; - styles = new TextStyle [length]; - 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] - clauses [i]; - styles [i] = style = new TextStyle (); - attr = getDisplayAttribute (langID, attrs [clauses [i]]); - if (attr != 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 != OS.TF_LS_NONE; - switch (attr.lsStyle) { - case OS.TF_LS_SQUIGGLE: - style.underlineStyle = SWT.UNDERLINE_ERROR; - 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 : SWT.UNDERLINE_SINGLE; - break; - } - } - } - } - } - } - OS.ImmReleaseContext (handle, hIMC); - } - String text = buffer != null ? buffer.toString () : ""; - Event event = new Event (); - event.detail = SWT.COMPOSITION_CHANGED; - event.text = text; - event.index = index; - event.count = 0; - event.ranges = ranges; - event.styles = styles; - event.wideCaret = OS.PRIMARYLANGID (langID) == OS.LANG_KOREAN; - sendEvent (SWT.ImeComposition, event); - } - return LRESULT.ONE; - } else { - /* - * Bug in Windows. On Korean Windows XP, the IME window - * for the Korean Input System (MS-IME 2002) always opens - * in the top left corner of the screen, despite the fact - * that ImmSetCompositionWindow() was called to position - * the IME when focus is gained. The fix is to position - * the IME on every WM_IME_COMPOSITION message. - */ - if (!OS.IsWinCE && OS.WIN32_VERSION == OS.VERSION (5, 1)) { - if (OS.IsDBLocale) { - short langID = OS.GetSystemDefaultUILanguage (); - short primaryLang = OS.PRIMARYLANGID (langID); - if (primaryLang == OS.LANG_KOREAN) { - if (caret != null && caret.isFocusCaret ()) { - POINT ptCurrentPos = new POINT (); - if (OS.GetCaretPos (ptCurrentPos)) { - COMPOSITIONFORM lpCompForm = new COMPOSITIONFORM (); - lpCompForm.dwStyle = OS.CFS_POINT; - lpCompForm.x = ptCurrentPos.x; - lpCompForm.y = ptCurrentPos.y; - int /*long*/ hIMC = OS.ImmGetContext (handle); - OS.ImmSetCompositionWindow (hIMC, lpCompForm); - OS.ImmReleaseContext (handle, hIMC); - } + if (ime != null) { + LRESULT result = ime.WM_IME_COMPOSITION (wParam, lParam); + if (result != null) return result; + } + + /* + * Bug in Windows. On Korean Windows XP, the IME window + * for the Korean Input System (MS-IME 2002) always opens + * in the top left corner of the screen, despite the fact + * that ImmSetCompositionWindow() was called to position + * the IME when focus is gained. The fix is to position + * the IME on every WM_IME_COMPOSITION message. + */ + if (!OS.IsWinCE && OS.WIN32_VERSION == OS.VERSION (5, 1)) { + if (OS.IsDBLocale) { + short langID = OS.GetSystemDefaultUILanguage (); + short primaryLang = OS.PRIMARYLANGID (langID); + if (primaryLang == OS.LANG_KOREAN) { + if (caret != null && caret.isFocusCaret ()) { + POINT ptCurrentPos = new POINT (); + if (OS.GetCaretPos (ptCurrentPos)) { + COMPOSITIONFORM lpCompForm = new COMPOSITIONFORM (); + lpCompForm.dwStyle = OS.CFS_POINT; + lpCompForm.x = ptCurrentPos.x; + lpCompForm.y = ptCurrentPos.y; + int /*long*/ hIMC = OS.ImmGetContext (handle); + OS.ImmSetCompositionWindow (hIMC, lpCompForm); + OS.ImmReleaseContext (handle, hIMC); } } } } } - return result; + return super.WM_IME_COMPOSITION (wParam, lParam); } LRESULT WM_IME_COMPOSITION_START (int /*long*/ wParam, int /*long*/ lParam) { - LRESULT result = super.WM_IME_COMPOSITION_START (wParam, lParam); - if (isInlineIMEEnabled ()) { - return LRESULT.ONE; + if (ime != null) { + LRESULT result = ime.WM_IME_COMPOSITION_START (wParam, lParam); + if (result != null) return result; } - return result; + return super.WM_IME_COMPOSITION_START (wParam, lParam); } LRESULT WM_IME_ENDCOMPOSITION (int /*long*/ wParam, int /*long*/ lParam) { - LRESULT result = super.WM_IME_ENDCOMPOSITION (wParam, lParam); - if (isInlineIMEEnabled ()) { - return LRESULT.ONE; + if (ime != null) { + LRESULT result = ime.WM_IME_ENDCOMPOSITION (wParam, lParam); + if (result != null) return result; } - return result; + return super.WM_IME_ENDCOMPOSITION (wParam, lParam); } LRESULT WM_INPUTLANGCHANGE (int /*long*/ wParam, int /*long*/ lParam) { @@ -562,14 +397,9 @@ LRESULT WM_INPUTLANGCHANGE (int /*long*/ wParam, int /*long*/ lParam) { } LRESULT WM_KILLFOCUS (int /*long*/ wParam, int /*long*/ lParam) { - if (isInlineIMEEnabled ()) { - int /*long*/ hIMC = OS.ImmGetContext (handle); - if (hIMC != 0) { - if (OS.ImmGetOpenStatus (hIMC)) { - OS.ImmNotifyIME (hIMC, OS.NI_COMPOSITIONSTR, OS.CPS_COMPLETE, 0); - } - OS.ImmReleaseContext (handle, hIMC); - } + if (ime != null) { + LRESULT result = ime.WM_KILLFOCUS (wParam, lParam); + if (result != null) return result; } LRESULT result = super.WM_KILLFOCUS (wParam, lParam); if (caret != null) caret.killFocus (); @@ -577,30 +407,9 @@ LRESULT WM_KILLFOCUS (int /*long*/ wParam, int /*long*/ lParam) { } LRESULT WM_LBUTTONDOWN (int /*long*/ wParam, int /*long*/ lParam) { - if (isInlineIMEEnabled ()) { - int /*long*/ hIMC = OS.ImmGetContext (handle); - if (hIMC != 0) { - if (OS.ImmGetOpenStatus (hIMC)) { - int length = OS.ImmGetCompositionString (hIMC, OS.GCS_COMPSTR, null, 0); - if (length > 0) { - Event event = new Event (); - event.detail = SWT.COMPOSITION_HITTEST; - event.x = OS.GET_X_LPARAM (lParam); - event.y = OS.GET_Y_LPARAM (lParam); - sendEvent (SWT.ImeComposition, event); - if (event.hitTest == SWT.HITTEST_INSIDE_COMPOSITION) { - int /*long*/ imeWnd = OS.ImmGetDefaultIMEWnd (handle); - int offset = event.index + event.trailing; - int trailing = event.trailing > 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 (handle, hIMC); - } + if (ime != null) { + LRESULT result = ime.WM_LBUTTONDOWN (wParam, lParam); + if (result != null) return result; } return super.WM_LBUTTONDOWN (wParam, lParam); } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Caret.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Caret.java index dc66d05047..9184870060 100755 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Caret.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Caret.java @@ -38,6 +38,7 @@ public class Caret extends Widget { Image image; Font font; LOGFONT oldFont; + int offset; /** * Constructs a new instance of this class given its parent @@ -171,6 +172,11 @@ public Point getLocation () { return new Point (x, y); } +public int getOffset () { + checkWidget (); + return offset; +} + /** * Returns the receiver's parent, which must be a <code>Canvas</code>. * @@ -278,7 +284,7 @@ void resizeIME () { if (!OS.GetCaretPos (ptCurrentPos)) return; int /*long*/ hwnd = parent.handle; int /*long*/ hIMC = OS.ImmGetContext (hwnd); - if (parent.isInlineIMEEnabled ()) { + if (parent.ime != null) { Point size = getSize (); CANDIDATEFORM lpCandidate = new CANDIDATEFORM (); lpCandidate.dwStyle = OS.CFS_EXCLUDE; @@ -520,6 +526,23 @@ public void setLocation (Point location) { } /** + * Sets the receiver's offset. + * + * @param offset the new offset for the receiver. + * + * @exception SWTException <ul> + * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> + * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> + * </ul> + * + * @since 3.4 + */ +public void setOffset (int offset) { + checkWidget (); + this.offset = Math.max (0, offset); +} + +/** * Sets the receiver's size to the point specified by the arguments. * * @param width the new width for the receiver diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/IME.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/IME.java new file mode 100644 index 0000000000..fb65fb9f35 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/IME.java @@ -0,0 +1,391 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ +package org.eclipse.swt.widgets; + + +import org.eclipse.swt.internal.win32.*; +import org.eclipse.swt.*; +import org.eclipse.swt.graphics.*; + +/** + * 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 extends Widget { + Canvas parent; + int caretOffset; + int startOffset; + int commitCount; + String text; + int [] ranges; + TextStyle [] styles; + + static final int WM_MSIME_MOUSE = OS.RegisterWindowMessage (new TCHAR (0, "MSIMEMouseOperation", true)); + + static final byte [] IID_ITfInputProcessorProfiles = new byte [16]; + static final byte [] IID_ITfDisplayAttributeProvider = new byte [16]; + static final byte [] CLSID_TF_InputProcessorProfiles = new byte [16]; + static final byte [] GUID_TFCAT_TIP_KEYBOARD = new byte [16]; + static { + OS.IIDFromString ("{1F02B6C5-7842-4EE6-8A0B-9A24183A95CA}\0".toCharArray (), IID_ITfInputProcessorProfiles); + OS.IIDFromString ("{fee47777-163c-4769-996a-6e9c50ad8f54}\0".toCharArray (), IID_ITfDisplayAttributeProvider); + OS.IIDFromString ("{33C53A50-F456-4884-B049-85FD643ECFED}\0".toCharArray (), CLSID_TF_InputProcessorProfiles); + OS.IIDFromString ("{34745C63-B2F0-4784-8B67-5E12C8701A31}\0".toCharArray (), GUID_TFCAT_TIP_KEYBOARD); + } + + /* TextLayout has a copy of these constants */ + static final int UNDERLINE_IME_DOT = 1 << 16; + static final int UNDERLINE_IME_DASH = 2 << 16; + static final int UNDERLINE_IME_THICK = 3 << 16; + +/** + * Prevents uninitialized instances from being created outside the package. + */ +IME () { +} + +/** + * + * @see SWT + */ +public IME (Canvas parent, int style) { + super (parent, style); + this.parent = parent; + createWidget (); +} + +void createWidget () { + text = ""; + startOffset = -1; + if (parent.getIME () == 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) { + int /*long*/ [] pProfiles = new int /*long*/ [1]; + int hr = OS.CoCreateInstance (CLSID_TF_InputProcessorProfiles, 0, OS.CLSCTX_INPROC_SERVER, IID_ITfInputProcessorProfiles, pProfiles); + TF_DISPLAYATTRIBUTE pda = null; + if (hr == OS.S_OK) { + byte [] pclsid = new byte [16]; + byte [] pguidProfile = new byte [16]; + /* pProfiles.GetDefaultLanguageProfile () */ + hr = OS.VtblCall (8, pProfiles [0], langid, GUID_TFCAT_TIP_KEYBOARD, pclsid, pguidProfile); + if (hr == OS.S_OK) { + int /*long*/ [] pProvider = new int /*long*/ [1]; + hr = OS.CoCreateInstance (pclsid, 0, OS.CLSCTX_INPROC_SERVER, IID_ITfDisplayAttributeProvider, pProvider); + if (hr == OS.S_OK) { + int /*long*/ [] pEnum = new int /*long*/ [1]; + /* pProvider.EnumDisplayAttributeInfo () */ + hr = OS.VtblCall (3, pProvider [0], pEnum); + if (hr == OS.S_OK) { + int /*long*/ [] pDispInfo = new int /*long*/ [1]; + TF_DISPLAYATTRIBUTE tempPda = new TF_DISPLAYATTRIBUTE (); + /* pEnum.Next () */ + while ((hr = OS.VtblCall (4, pEnum [0], 1, pDispInfo, null)) == OS.S_OK) { + /* pDispInfo.GetAttributeInfo(); */ + OS.VtblCall (5, pDispInfo [0], tempPda); + /* pDispInfo.Release () */ + OS.VtblCall (2, pDispInfo [0]); + if (tempPda.bAttr == attInfo) { + pda = tempPda; + break; + } + } + /* pEnum.Release () */ + hr = OS.VtblCall (2, pEnum [0]); + } + /* pProvider.Release () */ + hr = OS.VtblCall (2, pProvider [0]); + } + } + /* pProfiles.Release () */ + hr = OS.VtblCall (2, pProfiles [0]); + } + if (pda == 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 == OS.TF_ATTR_TARGET_CONVERTED; + break; + } + } + return pda; +} + +public int [] getRanges () { + checkWidget (); + return ranges != null ? ranges : new int [0]; +} + +public TextStyle [] getStyles () { + checkWidget (); + return styles != null ? styles : new TextStyle [0]; +} + +public String getText () { + checkWidget (); + return text; +} + +public boolean getWideCaret() { + checkWidget (); + int /*long*/ layout = OS.GetKeyboardLayout (0); + short langID = (short)OS.LOWORD (layout); + return OS.PRIMARYLANGID (langID) == OS.LANG_KOREAN; +} + +boolean isInlineIMEEnabled () { + if (OS.IsWinCE || OS.WIN32_VERSION < OS.VERSION (5, 1)) return false; + return OS.IsDBLocale && hooks (SWT.ImeComposition); +} + +void releaseParent () { + super.releaseParent (); + if (this == parent.getIME ()) parent.setIME (null); +} + +void releaseWidget () { + super.releaseWidget (); + parent = null; + text = null; + styles = null; + ranges = null; +} + +LRESULT WM_IME_COMPOSITION (int /*long*/ wParam, int /*long*/ lParam) { + if (isInlineIMEEnabled ()) { + ranges = null; + styles = null; + caretOffset = commitCount = 0; + int /*long*/ hwnd = parent.handle; + int /*long*/ hIMC = OS.ImmGetContext (hwnd); + int codePage = parent.getCodePage (); + if (hIMC != 0) { + TCHAR buffer = null; + if ((lParam & OS.GCS_RESULTSTR) != 0) { + int length = OS.ImmGetCompositionString (hIMC, OS.GCS_RESULTSTR, null, 0); + if (length > 0) { + buffer = new TCHAR (codePage, length / TCHAR.sizeof); + OS.ImmGetCompositionString (hIMC, OS.GCS_RESULTSTR, buffer, length); + Event event = new Event (); + event.detail = SWT.COMPOSITION_CHANGED; + event.start = startOffset; + event.end = startOffset + text.length(); + event.text = text = buffer != null ? buffer.toString () : ""; + commitCount = text.length (); + sendEvent (SWT.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 (SWT.KeyDown, event); + } + } + } + if ((lParam & OS.GCS_COMPSTR) == 0) return LRESULT.ONE; + } + buffer = null; + if ((lParam & OS.GCS_COMPSTR) != 0) { + int length = OS.ImmGetCompositionString (hIMC, OS.GCS_COMPSTR, null, 0); + if (length > 0) { + buffer = new TCHAR (codePage, length / TCHAR.sizeof); + OS.ImmGetCompositionString (hIMC, OS.GCS_COMPSTR, buffer, length); + if ((lParam & OS.GCS_CURSORPOS) != 0) { + caretOffset = OS.ImmGetCompositionString (hIMC, OS.GCS_CURSORPOS, null, 0); + } + int [] clauses = null; + if ((lParam & OS.GCS_COMPCLAUSE) != 0) { + length = OS.ImmGetCompositionStringW (hIMC, OS.GCS_COMPCLAUSE, (int [])null, 0); + if (length > 0) { + clauses = new int [length / 4]; + OS.ImmGetCompositionStringW (hIMC, OS.GCS_COMPCLAUSE, clauses, length); + } + } + if ((lParam & OS.GCS_COMPATTR) != 0 && clauses != null) { + length = OS.ImmGetCompositionStringA (hIMC, OS.GCS_COMPATTR, (byte [])null, 0); + if (length > 0) { + byte [] attrs = new byte [length]; + OS.ImmGetCompositionStringA (hIMC, OS.GCS_COMPATTR, attrs, length); + length = clauses.length - 1; + ranges = new int [length * 2]; + styles = new TextStyle [length]; + int /*long*/ layout = OS.GetKeyboardLayout (0); + short langID = (short)OS.LOWORD (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] - clauses [i]; + styles [i] = style = new TextStyle (); + attr = getDisplayAttribute (langID, attrs [clauses [i]]); + if (attr != 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 != OS.TF_LS_NONE; + switch (attr.lsStyle) { + case OS.TF_LS_SQUIGGLE: + style.underlineStyle = SWT.UNDERLINE_ERROR; + 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 : SWT.UNDERLINE_SINGLE; + break; + } + } + } + } + } + } + OS.ImmReleaseContext (hwnd, hIMC); + } + if (startOffset == -1) { + Caret caret = parent.getCaret(); + startOffset = caret != null ? caret.getOffset() : 0; + } + Event event = new Event (); + event.detail = SWT.COMPOSITION_CHANGED; + event.start = startOffset; + event.end = startOffset + text.length(); + event.text = text = buffer != null ? buffer.toString () : ""; + sendEvent (SWT.ImeComposition, event); + } + return LRESULT.ONE; + } + return null; +} + +LRESULT WM_IME_COMPOSITION_START (int /*long*/ wParam, int /*long*/ lParam) { + return isInlineIMEEnabled () ? LRESULT.ONE : null; +} + +LRESULT WM_IME_ENDCOMPOSITION (int /*long*/ wParam, int /*long*/ lParam) { + return isInlineIMEEnabled () ? LRESULT.ONE : null; +} + +LRESULT WM_KILLFOCUS (int /*long*/ wParam, int /*long*/ lParam) { + if (isInlineIMEEnabled ()) { + int /*long*/ hwnd = parent.handle; + int /*long*/ hIMC = OS.ImmGetContext (hwnd); + if (hIMC != 0) { + 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 (isInlineIMEEnabled ()) { + int /*long*/ hwnd = parent.handle; + int /*long*/ hIMC = OS.ImmGetContext (hwnd); + if (hIMC != 0) { + if (OS.ImmGetOpenStatus (hIMC)) { + if (OS.ImmGetCompositionString (hIMC, OS.GCS_COMPSTR, null, 0) > 0) { + Event event = new Event (); + event.detail = SWT.COMPOSITION_OFFSET; + event.x = OS.GET_X_LPARAM (lParam); + event.y = OS.GET_Y_LPARAM (lParam); + sendEvent (SWT.ImeComposition, event); + int offset = event.index; + int length = text.length(); + if (offset != -1 && startOffset != -1 && startOffset <= offset && offset < startOffset + length) { + int /*long*/ 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; +} + +} |