Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 178628 Details for
Bug 230854
[Bidi] support for text input widgets
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
[patch]
win32 patch including Combo
230854_f.diff (text/plain), 63.00 KB, created by
Lina Kemmel
on 2010-09-10 11:58:05 EDT
(
hide
)
Description:
win32 patch including Combo
Filename:
MIME Type:
Creator:
Lina Kemmel
Created:
2010-09-10 11:58:05 EDT
Size:
63.00 KB
patch
obsolete
>### Eclipse Workspace Patch 1.0 >#P org.eclipse.swt >Index: Eclipse SWT/common/org/eclipse/swt/SWT.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/SWT.java,v >retrieving revision 1.197 >diff -u -r1.197 SWT.java >--- Eclipse SWT/common/org/eclipse/swt/SWT.java 31 May 2010 16:44:15 -0000 1.197 >+++ Eclipse SWT/common/org/eclipse/swt/SWT.java 7 Sep 2010 21:16:59 -0000 >@@ -715,6 +715,20 @@ > */ > public static final int OpenDocument = 46; > >+ /** >+ * The open document event type (value is 47). >+ * >+ * @see org.eclipse.swt.widgets.Widget#addListener >+ * @see org.eclipse.swt.widgets.Display#addFilter >+ * @see org.eclipse.swt.widgets.Event >+ * >+ * @see org.eclipse.swt.widgets.Text#addSegmentListener >+ * @see org.eclipse.swt.events.SegmentEvent >+ * >+ * @since 3.6 >+ */ >+ public static final int GetSegments = 47; >+ > /* Event Details */ > > /** >Index: Eclipse SWT/common/org/eclipse/swt/events/SegmentEvent.java >=================================================================== >RCS file: Eclipse SWT/common/org/eclipse/swt/events/SegmentEvent.java >diff -N Eclipse SWT/common/org/eclipse/swt/events/SegmentEvent.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ Eclipse SWT/common/org/eclipse/swt/events/SegmentEvent.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,42 @@ >+/******************************************************************************* >+ * Copyright (c) 2000, 2010 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.events; >+ >+import org.eclipse.swt.widgets.Event; >+ >+/** >+ * @since 3.6 >+ * >+ */ >+public class SegmentEvent extends TypedEvent { >+ /** >+ * text >+ */ >+ public String text; >+ >+ /** >+ * bidi segments, see above >+ */ >+ public int [] segments; >+ >+ /** >+ * characters to be employed on the segment boundaries >+ */ >+ public char [] segmentsChars; >+ >+ >+ private static final long serialVersionUID = -89306787890624323L; >+ >+ public SegmentEvent(Event e) { >+ super(e); >+ text = e.text; >+ } >+} >Index: Eclipse SWT/common/org/eclipse/swt/events/SegmentListener.java >=================================================================== >RCS file: Eclipse SWT/common/org/eclipse/swt/events/SegmentListener.java >diff -N Eclipse SWT/common/org/eclipse/swt/events/SegmentListener.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ Eclipse SWT/common/org/eclipse/swt/events/SegmentListener.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,37 @@ >+/******************************************************************************* >+ * Copyright (c) 2000, 2010 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.events; >+ >+import org.eclipse.swt.internal.SWTEventListener; >+ >+/** >+ * This listener interface may be implemented in order to receive >+ * SegmentEvents. >+ * @see SegmentEvent >+ */ >+public interface SegmentListener extends SWTEventListener { >+ >+/** >+ * This method is called when a line needs to be reordered for >+ * measuring or rendering in a bidi locale. >+ * <p> >+ * The following event fields are used:<ul> >+ * <li>event.lineText line text (input)</li> >+ * <li>event.segmentsChars characters that should be inserted</li> >+ * <li>event.segments text offsets for segment characters</li></ul> >+ * >+ * @param event the given event >+ * @see SegmentEvent >+ * @see org.eclipse.swt.custom.BidiSegmentListener >+ */ >+public void lineGetSegments(SegmentEvent event); >+ >+} >Index: Eclipse SWT/common/org/eclipse/swt/widgets/Event.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/Event.java,v >retrieving revision 1.39 >diff -u -r1.39 Event.java >--- Eclipse SWT/common/org/eclipse/swt/widgets/Event.java 31 May 2010 16:44:09 -0000 1.39 >+++ Eclipse SWT/common/org/eclipse/swt/widgets/Event.java 7 Sep 2010 21:17:00 -0000 >@@ -203,6 +203,12 @@ > */ > public String text; > >+ //TODO DOC >+ public int[] segments; >+ >+ //TODO DOC >+ public char[] segmentsChars; >+ > /** > * depending on the event, a flag indicating whether the operation > * should be allowed. Setting this field to false will cancel the >Index: Eclipse SWT/common/org/eclipse/swt/widgets/TypedListener.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/widgets/TypedListener.java,v >retrieving revision 1.25 >diff -u -r1.25 TypedListener.java >--- Eclipse SWT/common/org/eclipse/swt/widgets/TypedListener.java 31 May 2010 16:44:09 -0000 1.25 >+++ Eclipse SWT/common/org/eclipse/swt/widgets/TypedListener.java 7 Sep 2010 21:56:39 -0000 >@@ -143,6 +143,13 @@ > ((FocusListener) eventListener).focusLost(new FocusEvent(e)); > break; > } >+ case SWT.GetSegments: { >+ SegmentEvent event = new SegmentEvent(e); >+ ((SegmentListener) eventListener).lineGetSegments(event); >+ e.segments = event.segments; >+ e.segmentsChars = event.segmentsChars; >+ break; >+ } > case SWT.Help: { > ((HelpListener) eventListener).helpRequested (new HelpEvent (e)); > break; >Index: Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/BidiSegmentEvent.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/BidiSegmentEvent.java,v >retrieving revision 1.16 >diff -u -r1.16 BidiSegmentEvent.java >--- Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/BidiSegmentEvent.java 31 May 2010 16:44:12 -0000 1.16 >+++ Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/BidiSegmentEvent.java 7 Sep 2010 21:16:58 -0000 >@@ -73,7 +73,7 @@ > * > * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> > */ >-public class BidiSegmentEvent extends TypedEvent { >+public class BidiSegmentEvent extends SegmentEvent { > > /** > * line start offset >@@ -84,19 +84,7 @@ > * line text > */ > public String lineText; >- >- /** >- * bidi segments, see above >- */ >- public int[] segments; > >- /** >- * characters to be used in the segment boundaries (optional) >- * >- * @since 3.6 >- */ >- public char[] segmentsChars; >- > static final long serialVersionUID = 3257846571587547957L; > > BidiSegmentEvent(StyledTextEvent e) { >Index: Eclipse SWT/win32/org/eclipse/swt/widgets/Text.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Text.java,v >retrieving revision 1.188 >diff -u -r1.188 Text.java >--- Eclipse SWT/win32/org/eclipse/swt/widgets/Text.java 23 Oct 2009 19:24:37 -0000 1.188 >+++ Eclipse SWT/win32/org/eclipse/swt/widgets/Text.java 10 Sep 2010 11:54:38 -0000 >@@ -58,7 +58,13 @@ > int tabs, oldStart, oldEnd; > boolean doubleClick, ignoreModify, ignoreVerify, ignoreCharacter; > String message; >- >+ int[] segments; >+ // Cached state for undo/redo >+ Object[][] undoData; >+ // XXX The following two variables are also required for other widgets, move them to some shared space >+ private static final char LTR_MARK = '\u200e'; >+ private static final char RTL_MARK = '\u200f'; >+ > /** > * The maximum number of characters that can be entered > * into a text widget. >@@ -251,6 +257,27 @@ > } > break; > } >+ case OS.WM_KEYDOWN: { >+ switch (wParam) { >+ case OS.VK_RIGHT: >+ case OS.VK_LEFT: >+ if (OS.GetKeyState(OS.VK_MENU) < 0) break; >+ // else FALL THROUGH >+ case OS.VK_DELETE: { >+ if (segments != null) { >+ clearSegments(true); >+ } >+ break; >+ } >+ } >+ break; >+ } >+ case OS.WM_CHAR: { >+ if (!ignoreCharacter && segments != null && OS.GetKeyState(OS.VK_CONTROL) >= 0 && OS.GetKeyState(OS.VK_MENU) >= 0) { >+ clearSegments(true); >+ } >+ break; >+ } > } > int /*long*/ code = OS.CallWindowProc (EditProc, hwnd, msg, wParam, lParam); > switch (msg) { >@@ -304,6 +331,33 @@ > > /** > * Adds the listener to the collection of listeners who will >+ * be notified when the receiver's text is verified, by sending >+ * it one of the messages defined in the <code>SegmentListener</code> >+ * interface. >+ * >+ * @param listener the listener which should be notified >+ * >+ * @exception IllegalArgumentException <ul> >+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</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> >+ * >+ * @see SegmentListener >+ * @see #removeSegmentListener >+ */ >+public void addSegmentListener (SegmentListener listener) { >+ checkWidget (); >+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); >+ clearSegments(true); >+ addListener(SWT.GetSegments, new TypedListener(listener)); >+ applySegments(); >+} >+ >+/** >+ * Adds the listener to the collection of listeners who will > * be notified when the control is selected by the user, by sending > * it one of the messages defined in the <code>SelectionListener</code> > * interface. >@@ -383,6 +437,7 @@ > checkWidget (); > if (string == null) error (SWT.ERROR_NULL_ARGUMENT); > string = Display.withCrLf (string); >+ if (segments != null) clearSegments(true); > int length = OS.GetWindowTextLength (handle); > if (hooks (SWT.Verify) || filters (SWT.Verify)) { > string = verifyText (string, length, length, null); >@@ -405,6 +460,40 @@ > OS.SendMessage (handle, OS.EM_REPLACESEL, 0, buffer); > ignoreCharacter = false; > OS.SendMessage (handle, OS.EM_SCROLLCARET, 0, 0); >+ if (hooks(SWT.GetSegments) || filters(SWT.GetSegments)) { >+ applySegments(); >+ } >+} >+ >+void applySegments() { >+ /* >+ * It's possible that while handling one event, another event that implies >+ * removal and addition of segments was fired. So we need to make sure that >+ * segments (if any) are cleared before the current apply operation >+ */ >+ if (segments != null) clearSegments(true); >+ int length = OS.GetWindowTextLength (handle); >+ int cp = getCodePage (); >+ TCHAR buffer = new TCHAR (cp, length + 1); >+ if (length > 0) OS.GetWindowText (handle, buffer, length + 1); >+ String string = buffer.toString (0, length); >+ Point selection = getSelection(); >+ string = getSegmentsText (string); >+ if (segments != null && segments.length > 0) { >+ boolean oldIgnoreCharacter = ignoreCharacter, oldIgnoreModify = ignoreModify, oldIgnoreVerify = ignoreVerify; >+ ignoreCharacter = ignoreModify = ignoreVerify = true; >+ /* >+ * SetWindowText empties the undo buffer and disables further undo >+ * operations. Sending OS.EM_REPLACESEL message. >+ */ >+ buffer = new TCHAR (cp, string, true); >+ OS.SendMessage(handle, OS.EM_SETSEL, 0, -1); >+ OS.SendMessage(handle, OS.EM_REPLACESEL, 1, buffer); >+ setSelection(selection); >+ ignoreCharacter = oldIgnoreCharacter; >+ ignoreModify = oldIgnoreModify; >+ ignoreVerify = oldIgnoreVerify; >+ } > } > > static int checkStyle (int style) { >@@ -432,6 +521,49 @@ > return style | SWT.SINGLE; > } > >+void clearSegments(boolean applyText) { >+ if (segments == null) return; >+ int nSegments = segments.length; >+ if (nSegments == 0) return; >+ int/*64*/ limit = (int/*64*/)OS.SendMessage (handle, OS.EM_GETLIMITTEXT, 0, 0) & 0x7fffffff; >+ if (limit < LIMIT) { >+ OS.SendMessage (handle, OS.EM_SETLIMITTEXT, Math.max(1, limit - nSegments), 0); >+ } >+ if (!applyText) { >+ segments = null; >+ return; >+ } >+ boolean oldIgnoreCharacter = ignoreCharacter, oldIgnoreModify = ignoreModify, oldIgnoreVerify = ignoreVerify; >+ ignoreCharacter = ignoreModify = ignoreVerify = true; >+ int length = OS.GetWindowTextLength (handle); >+ int cp = getCodePage (); >+ TCHAR buffer = new TCHAR (cp, length + 1); >+ if (length > 0) OS.GetWindowText (handle, buffer, length + 1); >+ Point selection = getSelection(); >+ String string = deprocessText(buffer.toString (0, length), 0, -1); >+ segments = null; >+ buffer = new TCHAR (cp, string, true); >+ /* >+ * SetWindowText empties the undo buffer and disables further undo >+ * operations. Sending OS.EM_REPLACESEL message. >+ */ >+ OS.SendMessage(handle, OS.EM_SETSEL, 0, -1); >+ if (OS.SendMessage (handle, OS.EM_CANUNDO, 0, 0) != 0) { >+ /* >+ * Empty text buffer so that if there be no coming text deletion, then >+ * undoing will result in empty text not segmented text. >+ */ >+ OS.SendMessage(handle, OS.EM_REPLACESEL, 1, new TCHAR(cp, "", true)); >+ OS.SendMessage(handle, OS.EM_REPLACESEL, 1, buffer); >+ } else { >+ OS.SendMessage(handle, OS.EM_REPLACESEL, 0, buffer); >+ } >+ setSelection(selection); >+ ignoreCharacter = oldIgnoreCharacter; >+ ignoreModify = oldIgnoreModify; >+ ignoreVerify = oldIgnoreVerify; >+} >+ > /** > * Clears the selection. > * >@@ -574,6 +706,30 @@ > return OS.GetSysColor ((bits & OS.ES_READONLY) != 0 ? OS.COLOR_3DFACE : OS.COLOR_WINDOW); > } > >+String deprocessText(String text, int start, int end) { >+ if (text == null || segments == null) return text; >+ int length = text.length(); >+ if (length == 0) return text; >+ int nSegments = segments.length; >+ if (nSegments == 0) return text; >+ if (end == -1) end = length; >+ if (start > segments[nSegments - 1] || end <= segments[0]) return text; >+ char[] oldChars = new char[length]; >+ text.getChars(0, length, oldChars, 0); >+ char[] newChars = new char[length]; >+ int nLeadSegments = 0; >+ while (start - nLeadSegments > segments[nLeadSegments]) nLeadSegments++; >+ int segmentCount = nLeadSegments; >+ for (int i = 0; i < length; i++) { >+ if (segmentCount < nSegments && i + start - segmentCount == segments[segmentCount]) { >+ ++segmentCount; >+ } else { >+ newChars[i - segmentCount + nLeadSegments] = oldChars[i]; >+ } >+ } >+ return new String(newChars, 0, newChars.length - segmentCount + nLeadSegments); >+} >+ > boolean dragDetect (int /*long*/ hwnd, int x, int y, boolean filter, boolean [] detect, boolean [] consume) { > if (filter) { > int [] start = new int [1], end = new int [1]; >@@ -706,6 +862,7 @@ > * pixel coordinates (0,0). > */ > int position = getCaretPosition (); >+ if (segments != null) position = translateOffset (position); > int /*long*/ caretPos = OS.SendMessage (handle, OS.EM_POSFROMCHAR, position, 0); > if (caretPos == -1) { > caretPos = 0; >@@ -798,6 +955,7 @@ > } > } > if (!OS.IsUnicode && OS.IsDBLocale) caret = mbcsToWcsPos (caret); >+ if (segments != null) caret = untranslateOffset (caret); > return caret; > } > >@@ -815,6 +973,7 @@ > checkWidget (); > int length = OS.GetWindowTextLength (handle); > if (!OS.IsUnicode && OS.IsDBLocale) length = mbcsToWcsPos (length); >+ if (segments != null) length -= segments.length; > return length; > } > >@@ -996,9 +1155,51 @@ > int /*long*/ lParam = OS.MAKELPARAM (point.x, point.y); > int position = OS.LOWORD (OS.SendMessage (handle, OS.EM_CHARFROMPOS, 0, lParam)); > if (!OS.IsUnicode && OS.IsDBLocale) position = mbcsToWcsPos (position); >+ if (segments != null) position = untranslateOffset(position); > return position; > } > >+String getSegmentsText(String text) { >+ if (!hooks(SWT.GetSegments) && !filters(SWT.GetSegments)) return text; >+ Event event = new Event(); >+ event.text = text; >+ event.segments = segments; >+ sendEvent(SWT.GetSegments, event); >+ segments = event.segments; >+ if (segments == null) return text; >+ int nSegments = segments.length; >+ if (nSegments == 0) return text; >+ >+ for (int i = 1, lineLength = text == null ? 0 : text.length(); i < nSegments; i++) { >+ if (event.segments[i] < event.segments[i - 1] || event.segments[i] > lineLength) { >+ SWT.error(SWT.ERROR_INVALID_ARGUMENT); >+ } >+ } >+ int/*64*/ limit = (int/*64*/)OS.SendMessage (handle, OS.EM_GETLIMITTEXT, 0, 0) & 0x7fffffff; >+ OS.SendMessage (handle, OS.EM_SETLIMITTEXT, limit + Math.min(nSegments, LIMIT - limit), 0); >+ char[] segmentsChars = event.segmentsChars; >+ int length = text.length(); >+ char[] oldChars = new char[length]; >+ text.getChars(0, length, oldChars, 0); >+ char[] newChars = new char[length + nSegments]; >+ int charCount = 0, segmentCount = 0; >+ char defaultSeparator = getOrientation() == SWT.RIGHT_TO_LEFT ? RTL_MARK : LTR_MARK; >+ while (charCount < length) { >+ if (segmentCount < nSegments && charCount == segments[segmentCount]) { >+ char separator = segmentsChars != null && segmentsChars.length > segmentCount ? segmentsChars[segmentCount] : defaultSeparator; >+ newChars[charCount + segmentCount++] = separator; >+ } else { >+ newChars[charCount + segmentCount] = oldChars[charCount++]; >+ } >+ } >+ while (segmentCount < nSegments) { >+ segments[segmentCount] = charCount; >+ char separator = segmentsChars != null && segmentsChars.length > segmentCount ? segmentsChars[segmentCount] : defaultSeparator; >+ newChars[charCount + segmentCount++] = separator; >+ } >+ return new String(newChars, 0, newChars.length); >+} >+ > /** > * Returns a <code>Point</code> whose x coordinate is the > * character position representing the start of the selected >@@ -1025,6 +1226,15 @@ > start [0] = mbcsToWcsPos (start [0]); > end [0] = mbcsToWcsPos (end [0]); > } >+ if (segments != null) { >+ if (start[0] == end[0]) { >+ start [0] = end [0] = untranslateOffset (start [0]); >+ } >+ else { >+ start [0] = untranslateOffset (start [0]); >+ end [0] = untranslateOffset (end [0]); >+ } >+ } > return new Point (start [0], end [0]); > } > >@@ -1063,6 +1273,10 @@ > if (start [0] == end [0]) return ""; > TCHAR buffer = new TCHAR (getCodePage (), length + 1); > OS.GetWindowText (handle, buffer, length + 1); >+ if (segments != null) { >+ String text = buffer.toString (start [0], end [0] - start [0]); >+ return deprocessText(text, start [0], end [0]); >+ } > return buffer.toString (start [0], end [0] - start [0]); > } > >@@ -1120,7 +1334,11 @@ > if (length == 0) return ""; > TCHAR buffer = new TCHAR (getCodePage (), length + 1); > OS.GetWindowText (handle, buffer, length + 1); >- return buffer.toString (0, length); >+ String text = buffer.toString (0, length); >+ if (segments != null) { >+ return deprocessText(text, 0, -1); >+ } >+ return text; > } > > /** >@@ -1146,6 +1364,7 @@ > if (!(start <= end && 0 <= end)) return ""; > int length = OS.GetWindowTextLength (handle); > if (!OS.IsUnicode && OS.IsDBLocale) length = mbcsToWcsPos (length); >+ if (segments != null) length -= segments.length; > end = Math.min (end, length - 1); > if (start > end) return ""; > start = Math.max (0, start); >@@ -1175,7 +1394,9 @@ > */ > public int getTextLimit () { > checkWidget (); >- return (int)/*64*/OS.SendMessage (handle, OS.EM_GETLIMITTEXT, 0, 0) & 0x7FFFFFFF; >+ int/*64*/ limit = (int)/*64*/OS.SendMessage (handle, OS.EM_GETLIMITTEXT, 0, 0) & 0x7FFFFFFF; >+ if (segments != null && limit < LIMIT) limit = Math.max(1, limit - segments.length); >+ return limit; > } > > /** >@@ -1251,6 +1472,10 @@ > checkWidget (); > if (string == null) error (SWT.ERROR_NULL_ARGUMENT); > string = Display.withCrLf (string); >+ if (hooks(SWT.GetSegments) || filters(SWT.GetSegments)) { >+ clearSegments(true); >+ saveUndoData(OS.WM_PASTE, 0, string); >+ } > if (hooks (SWT.Verify) || filters (SWT.Verify)) { > int [] start = new int [1], end = new int [1]; > OS.SendMessage (handle, OS.EM_GETSEL, start, end); >@@ -1272,6 +1497,9 @@ > ignoreCharacter = true; > OS.SendMessage (handle, OS.EM_REPLACESEL, 0, buffer); > ignoreCharacter = false; >+ if (hooks(SWT.GetSegments) || filters(SWT.GetSegments)) { >+ applySegments(); >+ } > } > > int mbcsToWcsPos (int mbcsPos) { >@@ -1363,6 +1591,31 @@ > > /** > * Removes the listener from the collection of listeners who will >+ * be notified when the receiver's text is modified. >+ * >+ * @param listener the listener which should no longer be notified >+ * >+ * @exception IllegalArgumentException <ul> >+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</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> >+ * >+ * @see SegmentListener >+ * @see #addSegmentListener >+ */ >+public void removeSegmentListener(SegmentListener listener) { >+ checkWidget(); >+ if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); >+ clearSegments(true); >+ eventTable.unhook (SWT.GetSegments, listener); >+ applySegments(); >+} >+ >+/** >+ * Removes the listener from the collection of listeners who will > * be notified when the control is selected by the user. > * > * @param listener the listener which should no longer be notified >@@ -1802,6 +2055,7 @@ > */ > public void setSelection (int start) { > checkWidget (); >+ if (segments != null) start = translateOffset(start); > if (!OS.IsUnicode && OS.IsDBLocale) start = wcsToMbcsPos (start); > OS.SendMessage (handle, OS.EM_SETSEL, start, start); > OS.SendMessage (handle, OS.EM_SCROLLCARET, 0, 0); >@@ -1834,6 +2088,14 @@ > */ > public void setSelection (int start, int end) { > checkWidget (); >+ if (segments != null) { >+ if (start == end) { >+ start = end = translateOffset(start); >+ } else { >+ start = translateOffset(start); >+ end = translateOffset(end); >+ } >+ } > if (!OS.IsUnicode && OS.IsDBLocale) { > start = wcsToMbcsPos (start); > end = wcsToMbcsPos (end); >@@ -1955,10 +2217,12 @@ > string = verifyText (string, 0, length, null); > if (string == null) return; > } >+ if (segments != null) clearSegments(false); > int limit = (int)/*64*/OS.SendMessage (handle, OS.EM_GETLIMITTEXT, 0, 0) & 0x7FFFFFFF; > if (string.length () > limit) string = string.substring (0, limit); > TCHAR buffer = new TCHAR (getCodePage (), string, true); > OS.SetWindowText (handle, buffer); >+ applySegments(); > /* > * Bug in Windows. When the widget is multi line > * text widget, it does not send a WM_COMMAND with >@@ -2000,7 +2264,11 @@ > public void setTextLimit (int limit) { > checkWidget (); > if (limit == 0) error (SWT.ERROR_CANNOT_BE_ZERO); >- OS.SendMessage (handle, OS.EM_SETLIMITTEXT, limit, 0); >+ if (segments != null && limit > 0) { >+ OS.SendMessage (handle, OS.EM_SETLIMITTEXT, limit + Math.min(segments.length, LIMIT - limit), 0); >+ } else { >+ OS.SendMessage (handle, OS.EM_SETLIMITTEXT, limit, 0); >+ } > } > > /** >@@ -2042,6 +2310,22 @@ > OS.SendMessage (handle, OS.EM_SCROLLCARET, 0, 0); > } > >+int translateOffset(int offset) { >+ if (segments == null) return offset; >+ for (int i = 0, nSegments = segments.length; i < nSegments && offset - i >= segments[i]; i++) { >+ offset++; >+ } >+ return offset; >+} >+ >+int untranslateOffset(int offset) { >+ if (segments == null) return offset; >+ for (int i = 0, nSegments = segments.length; i < nSegments && offset > segments[i]; i++) { >+ offset--; >+ } >+ return offset; >+} >+ > String verifyText (String string, int start, int end, Event keyEvent) { > if (ignoreVerify) return string; > Event event = new Event (); >@@ -2154,6 +2438,69 @@ > } > > int /*long*/ windowProc (int /*long*/ hwnd, int msg, int /*long*/ wParam, int /*long*/ lParam) { >+ boolean processSegments = false, saveUndoData = false, redraw = false; >+ int code; >+ if (hooks(SWT.GetSegments) || filters(SWT.GetSegments)) { >+ switch (msg) { >+ case OS.EM_UNDO: >+ case OS.WM_UNDO: { >+ loadUndoData(); >+ return 1; >+ } >+ case OS.WM_LBUTTONUP: { >+ saveUndoData(0, 0, null); >+ break; >+ } >+ case OS.WM_KEYDOWN: { >+ switch (wParam) { >+ case OS.VK_DELETE: { >+ processSegments = saveUndoData = true; >+ break; >+ } >+ case OS.VK_RIGHT: >+ case OS.VK_LEFT: { >+ processSegments = segments != null && OS.GetKeyState(OS.VK_MENU) >= 0; >+ // FALL THROUGH >+ } >+ case OS.VK_UP: >+ case OS.VK_DOWN: >+ case OS.VK_HOME: >+ case OS.VK_END: { >+ saveUndoData(0, 0, null); >+ break; >+ } >+ } >+ break; >+ } >+ case OS.WM_COPY: { >+ processSegments = segments != null; >+ break; >+ } >+ case OS.WM_CHAR: { >+ if (OS.GetKeyState(OS.VK_CONTROL) >= 0 && OS.GetKeyState(OS.VK_MENU) >= 0) { >+ saveUndoData = true; >+ processSegments = !ignoreCharacter; >+ } >+ break; >+ } >+ case OS.WM_PASTE: >+ case OS.WM_CUT: >+ case OS.WM_CLEAR: { >+ processSegments = saveUndoData = true; >+ break; >+ } >+ } >+ } >+ if (processSegments) { >+ if (getDrawing () && OS.IsWindowVisible (handle)) { >+ redraw = true; >+ OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0); >+ } >+ clearSegments(true); >+ } >+ if (saveUndoData) { >+ saveUndoData(msg, wParam, null); >+ } > if (msg == OS.EM_UNDO) { > int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); > if ((bits & OS.ES_MULTILINE) == 0) { >@@ -2161,13 +2508,24 @@ > if (result != null) return result.value; > return callWindowProc (hwnd, OS.EM_UNDO, wParam, lParam); > } >- } >- if (msg == Display.SWT_RESTORECARET) { >+ } else if (msg == Display.SWT_RESTORECARET) { > callWindowProc (hwnd, OS.WM_KILLFOCUS, 0, 0); > callWindowProc (hwnd, OS.WM_SETFOCUS, 0, 0); > return 1; > } >- return super.windowProc (hwnd, msg, wParam, lParam); >+ code = super.windowProc (hwnd, msg, wParam, lParam); >+ if (processSegments) { >+ applySegments(); >+ if (redraw) { >+ OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0); >+ if (OS.IsWinCE) { >+ OS.InvalidateRect (handle, null, true); >+ } else { >+ OS.RedrawWindow (handle, null, 0, OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE); >+ } >+ } >+ } >+ return code; > } > > LRESULT WM_CHAR (int /*long*/ wParam, int /*long*/ lParam) { >@@ -2550,6 +2908,8 @@ > style |= SWT.LEFT_TO_RIGHT; > } > OS.SetWindowLong (handle, OS.GWL_EXSTYLE, bits); >+ } else if (hooks(SWT.GetSegments) || filters(SWT.GetSegments)) { >+ applySegments(); > } > fixAlignment(); > break; >@@ -2557,4 +2917,104 @@ > return super.wmCommandChild (wParam, lParam); > } > >+void loadUndoData() { >+ if (undoData != null && OS.SendMessage (handle, OS.EM_CANUNDO, 0, 0) != 0) { >+ // Delete inserted text and insert deleted text >+ boolean oldIgnoreCharacter = ignoreCharacter, oldIgnoreModify = ignoreModify; >+ boolean applySegments = false; >+ TCHAR buffer; >+ if (undoData[0][0] != null) { // inserted text >+ int[] insertPoint = (int[])undoData[0][1]; >+ if (insertPoint == null || insertPoint.length < 1) SWT.error(SWT.ERROR_INVALID_ARGUMENT); >+ buffer = new TCHAR(getCodePage(), (String)undoData[0][0], true); >+ if (segments != null) { >+ applySegments = true; >+ clearSegments(true); >+ } >+ int end = insertPoint[0] + buffer.strlen(); >+ OS.SendMessage (handle, OS.EM_SETSEL, insertPoint[0], end); >+ ignoreCharacter = ignoreModify = true; >+ OS.SendMessage(handle, OS.EM_REPLACESEL, 1, new TCHAR (getCodePage(), "", true)); >+ } >+ if (undoData[1][0] != null) { // deleted text >+ int[] deletePoint = (int[])undoData[1][1]; >+ if (deletePoint == null || deletePoint.length < 1) SWT.error(SWT.ERROR_INVALID_ARGUMENT); >+ buffer = new TCHAR(getCodePage(), (String)undoData[1][0], true); >+ if (segments != null) { >+ applySegments = true; >+ clearSegments(true); >+ } >+ OS.SendMessage (handle, OS.EM_SETSEL, deletePoint[0], deletePoint[0]); >+ ignoreCharacter = ignoreModify = true; >+ OS.SendMessage(handle, OS.EM_REPLACESEL, 1, buffer); >+ int end = deletePoint[0] + buffer.strlen(); >+ OS.SendMessage (handle, OS.EM_SETSEL, deletePoint[0], end); >+ } >+ ignoreCharacter = oldIgnoreCharacter; >+ ignoreModify = oldIgnoreModify; >+ Object[] data = undoData[0]; >+ undoData[0] = undoData[1]; >+ undoData[1] = data; >+ if (applySegments) { >+ applySegments(); >+ } >+ } >+} >+ >+void saveUndoData(int msg, int /*long*/ wParam, String insertText) { >+ if (msg == 0) { >+ if (undoData != null) undoData[0][2] = undoData[1][2] = new Object(); >+ return; >+ } >+ if (undoData == null) undoData = new Object[2][3]; >+ int[] start = new int[1], end = new int[1]; >+ OS.SendMessage (handle, OS.EM_GETSEL, start, end); >+ if (insertText != null || msg == OS.WM_PASTE || msg == OS.WM_CHAR && wParam != OS.VK_BACK) { >+ if (undoData[0][2] != null || undoData[1][2] != null) { >+ undoData[0][0] = undoData[0][1] = undoData[0][2] = null; >+ undoData[1][0] = undoData[1][1] = undoData[1][2] = null; >+ } >+ String oldInsertText = (String)undoData[0][0]; >+ if (insertText != null) undoData[0][0] = insertText; >+ else if (msg == OS.WM_CHAR) undoData[0][0] = String.valueOf((char)wParam); >+ else undoData[0][0] = getClipboardText(); >+ if (start[0] == end[0]) { >+ if (undoData[0][1] == null) undoData[0][1] = start; >+ if (oldInsertText != null) undoData[0][0] = oldInsertText + undoData[0][0]; >+ } else { >+ undoData[0][1] = start; >+ undoData[1][0] = getSelectionText(); >+ undoData[1][1] = new int[] {start[0]}; >+ } >+ } else { >+ if (msg == OS.WM_CHAR && end[0] <= 0) return; >+ if (msg == OS.WM_CUT && start[0] == end[0]) return; >+ int length = OS.GetWindowTextLength (handle); >+ if (msg == OS.WM_KEYDOWN && start[0] >= length) return; >+ if (undoData[0][2] != null || undoData[1][2] != null) { >+ undoData[0][0] = undoData[0][1] = undoData[0][2] = null; >+ undoData[1][0] = undoData[1][1] = undoData[1][2] = null; >+ } >+ undoData[0][0] = undoData[0][1] = null; >+ String oldDeleteText = (String)undoData[1][0]; >+ if (start[0] != end[0]) { >+ undoData[1][0] = getSelectionText(); >+ if (oldDeleteText != null) undoData[1][0] = undoData[1][0] + oldDeleteText; >+ if (undoData[1][1] == null) undoData[1][1] = start; >+ } else if (msg != OS.WM_CUT) { >+ TCHAR buffer = new TCHAR (getCodePage(), length + 1); >+ OS.GetWindowText (handle, buffer, length + 1); >+ if (msg == OS.WM_CHAR) { >+ start[0]--; >+ undoData[1][0] = buffer.toString (start[0], end[0] - start[0]); >+ if (oldDeleteText != null) undoData[1][0] = undoData[1][0] + oldDeleteText; >+ undoData[1][1] = start; >+ } else { >+ undoData[1][0] = buffer.toString (start[0], end[0] - start[0] + 1); >+ if (oldDeleteText != null) undoData[1][0] = oldDeleteText + undoData[1][0]; >+ if (undoData[1][1] == null) undoData[1][1] = start; >+ } >+ } >+ } >+} > } >Index: Eclipse SWT/win32/org/eclipse/swt/widgets/Combo.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Combo.java,v >retrieving revision 1.176 >diff -u -r1.176 Combo.java >--- Eclipse SWT/win32/org/eclipse/swt/widgets/Combo.java 5 Jul 2010 19:00:00 -0000 1.176 >+++ Eclipse SWT/win32/org/eclipse/swt/widgets/Combo.java 10 Sep 2010 13:31:33 -0000 >@@ -69,7 +69,13 @@ > * that the text field in an instance of this class can hold > */ > public static final int LIMIT; >- >+ >+ private static final char LTR_MARK = '\u200e'; >+ private static final char RTL_MARK = '\u200f'; >+ >+ int[] segments; >+ int[][] itemSegments; >+ > /* > * These values can be different on different platforms. > * Therefore they are not initialized in the declaration >@@ -225,6 +231,34 @@ > > /** > * Adds the listener to the collection of listeners who will >+ * be notified when the receiver's text is verified, by sending >+ * it one of the messages defined in the <code>SegmentListener</code> >+ * interface. >+ * >+ * @param listener the listener which should be notified >+ * >+ * @exception IllegalArgumentException <ul> >+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</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> >+ * >+ * @see SegmentListener >+ * @see #removeSegmentListener >+ */ >+public void addSegmentListener (SegmentListener listener) { >+ checkWidget (); >+ if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); >+ clearSegments(true); >+ addListener(SWT.GetSegments, new TypedListener(listener)); >+ applySegments(); >+ applyItemsSegments(); >+} >+ >+/** >+ * Adds the listener to the collection of listeners who will > * be notified when the user changes the receiver's selection, by sending > * it one of the messages defined in the <code>SelectionListener</code> > * interface. >@@ -283,6 +317,44 @@ > addListener (SWT.Verify, typedListener); > } > >+void applyItemsSegments() { >+ int count = getItemCount (); >+ while (count-- > 0) { >+ setItem (count, getItem (count)); >+ } >+} >+ >+void applySegments() { >+ if (segments != null) clearSegments(true); >+ int /*long*/ hwndText = OS.GetDlgItem (handle, CBID_EDIT); >+ int length = OS.GetWindowTextLength (hwndText); >+ int cp = getCodePage (); >+ TCHAR buffer = new TCHAR (cp, length + 1); >+ if (length > 0) OS.GetWindowText (hwndText, buffer, length + 1); >+ String string = buffer.toString (0, length); >+ Event event = getSegments(string); >+ Point selection = getSelection(); >+ if (event != null) { >+ segments = event.segments; >+ if (segments != null && segments.length > 0) { >+ boolean oldIgnoreCharacter = ignoreCharacter, oldIgnoreModify = ignoreModify; >+ ignoreCharacter = ignoreModify = true; >+ int/*64*/ limit = (int/*64*/)OS.SendMessage (hwndText, OS.EM_GETLIMITTEXT, 0, 0) & 0x7fffffff; >+ OS.SendMessage (hwndText, OS.EM_SETLIMITTEXT, limit + Math.min(segments.length, LIMIT - limit), 0); >+ /* >+ * SetWindowText empties the undo buffer and disables further undo >+ * operations. Sending OS.EM_REPLACESEL message. >+ */ >+ buffer = new TCHAR (cp, getSegmentsText(string, event), true); >+ OS.SendMessage(hwndText, OS.EM_SETSEL, 0, -1); >+ OS.SendMessage(hwndText, OS.EM_REPLACESEL, 1, buffer); >+ setSelection(selection); >+ ignoreCharacter = oldIgnoreCharacter; >+ ignoreModify = oldIgnoreModify; >+ } >+ } >+} >+ > int /*long*/ callWindowProc (int /*long*/ hwnd, int msg, int /*long*/ wParam, int /*long*/ lParam) { > if (handle == 0) return 0; > if (hwnd == handle) { >@@ -302,6 +374,28 @@ > int /*long*/ hwndText = OS.GetDlgItem (handle, CBID_EDIT); > if (hwnd == hwndText) { > if (lockText && msg == OS.WM_SETTEXT) return 0; >+ switch (msg) { >+ case OS.WM_KEYDOWN: { >+ switch (wParam) { >+ case OS.VK_RIGHT: >+ case OS.VK_LEFT: >+ if (OS.GetKeyState(OS.VK_MENU) < 0) break; >+ // else FALL THROUGH >+ case OS.VK_DELETE: { >+ if (segments != null) { >+ clearSegments(true); >+ } >+ } >+ } >+ break; >+ } >+ case OS.WM_CHAR: { >+ if (!ignoreCharacter && segments != null && OS.GetKeyState(OS.VK_CONTROL) >= 0 && OS.GetKeyState(OS.VK_MENU) >= 0) { >+ clearSegments(true); >+ } >+ break; >+ } >+ } > return OS.CallWindowProc (EditProc, hwnd, msg, wParam, lParam); > } > int /*long*/ hwndList = OS.GetDlgItem (handle, CBID_LIST); >@@ -360,6 +454,49 @@ > return style; > } > >+void clearSegments(boolean applyText) { >+ if (segments == null) return; >+ int nSegments = segments.length; >+ if (nSegments == 0) return; >+ int /*long*/ hwndText = OS.GetDlgItem (handle, CBID_EDIT); >+ int/*64*/ limit = (int/*64*/)OS.SendMessage (hwndText, OS.EM_GETLIMITTEXT, 0, 0) & 0x7fffffff; >+ if (limit < LIMIT) { >+ OS.SendMessage (hwndText, OS.EM_SETLIMITTEXT, Math.max(1, limit - nSegments), 0); >+ } >+ if (!applyText) { >+ segments = null; >+ return; >+ } >+ boolean oldIgnoreCharacter = ignoreCharacter, oldIgnoreModify = ignoreModify; >+ ignoreCharacter = ignoreModify = true; >+ int length = OS.GetWindowTextLength (hwndText); >+ int cp = getCodePage (); >+ TCHAR buffer = new TCHAR (cp, length + 1); >+ if (length > 0) OS.GetWindowText (hwndText, buffer, length + 1); >+ Point selection = getSelection(); >+ String string = deprocessText(buffer.toString (0, length), segments); >+ segments = null; >+ buffer = new TCHAR (cp, string, true); >+ /* >+ * SetWindowText empties the undo buffer and disables further undo >+ * operations. Sending OS.EM_REPLACESEL message. >+ */ >+ OS.SendMessage(hwndText, OS.EM_SETSEL, 0, -1); >+ if (OS.SendMessage (hwndText, OS.EM_CANUNDO, 0, 0) != 0) { >+ /* >+ * Empty text buffer so that if there be no coming text deletion, then >+ * undoing will result in empty text not segmented text. >+ */ >+ OS.SendMessage(hwndText, OS.EM_REPLACESEL, 1, new TCHAR(cp, "", true)); >+ OS.SendMessage(hwndText, OS.EM_REPLACESEL, 1, buffer); >+ } else { >+ OS.SendMessage(hwndText, OS.EM_REPLACESEL, 0, buffer); >+ } >+ setSelection(selection); >+ ignoreCharacter = oldIgnoreCharacter; >+ ignoreModify = oldIgnoreModify; >+} >+ > /** > * Sets the selection in the receiver's text field to an empty > * selection starting just before the first character. If the >@@ -574,6 +711,26 @@ > return OS.GetSysColor (OS.COLOR_WINDOW); > } > >+String deprocessText(String text, int[] segments) { >+ if (text == null || segments == null) return text; >+ int length = text.length(); >+ if (length == 0) return text; >+ int nSegments = segments.length; >+ if (nSegments == 0) return text; >+ char[] oldChars = new char[length]; >+ text.getChars(0, length, oldChars, 0); >+ char[] newChars = new char[length]; >+ int segmentCount = 0; >+ for (int i = 0; i < length; i++) { >+ if (segmentCount < nSegments && i - segmentCount == segments[segmentCount]) { >+ ++segmentCount; >+ } else { >+ newChars[i - segmentCount] = oldChars[i]; >+ } >+ } >+ return new String(newChars, 0, newChars.length - segmentCount); >+} >+ > void deregister () { > super.deregister (); > int /*long*/ hwndText = OS.GetDlgItem (handle, CBID_EDIT); >@@ -668,7 +825,12 @@ > if (length != OS.CB_ERR) { > TCHAR buffer = new TCHAR (getCodePage (), length + 1); > int result = (int)/*64*/OS.SendMessage (handle, OS.CB_GETLBTEXT, index, buffer); >- if (result != OS.CB_ERR) return buffer.toString (0, length); >+ if (result != OS.CB_ERR) { >+ if (itemSegments != null && itemSegments.length > index) { >+ return deprocessText(buffer.toString (0, length), itemSegments[index]); >+ } >+ return buffer.toString (0, length); >+ } > } > int count = (int)/*64*/OS.SendMessage (handle, OS.CB_GETCOUNT, 0, 0); > if (0 <= index && index < count) error (SWT.ERROR_CANNOT_GET_ITEM); >@@ -805,6 +967,49 @@ > checkWidget(); > return style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT); > } >+Event getSegments(String string) { >+ if (!hooks(SWT.GetSegments) && !filters(SWT.GetSegments)) return null; >+ Event event = new Event(); >+ event.text = string; >+ sendEvent(SWT.GetSegments, event); >+ if (event.segments != null) { >+ for (int i = 1, segmentCount = event.segments.length, lineLength = string == null ? 0 : string.length(); i < segmentCount; i++) { >+ if (event.segments[i] < event.segments[i - 1] || event.segments[i] > lineLength) { >+ SWT.error(SWT.ERROR_INVALID_ARGUMENT); >+ } >+ } >+ } >+ return event; >+} >+ >+String getSegmentsText(String text, Event event) { >+ if (text == null || event == null) return text; >+ int[] segments = event.segments; >+ if (segments == null) return text; >+ int nSegments = segments.length; >+ if (nSegments == 0) return text; >+ char[] segmentsChars = /*event == null ? this.segmentsChars : */event.segmentsChars; >+ int length = text.length(); >+ char[] oldChars = new char[length]; >+ text.getChars(0, length, oldChars, 0); >+ char[] newChars = new char[length + nSegments]; >+ int charCount = 0, segmentCount = 0; >+ char defaultSeparator = getOrientation() == SWT.RIGHT_TO_LEFT ? RTL_MARK : LTR_MARK; >+ while (charCount < length) { >+ if (segmentCount < nSegments && charCount == segments[segmentCount]) { >+ char separator = segmentsChars != null && segmentsChars.length > segmentCount ? segmentsChars[segmentCount] : defaultSeparator; >+ newChars[charCount + segmentCount++] = separator; >+ } else { >+ newChars[charCount + segmentCount] = oldChars[charCount++]; >+ } >+ } >+ while (segmentCount < nSegments) { >+ segments[segmentCount] = charCount; >+ char separator = segmentsChars != null && segmentsChars.length > segmentCount ? segmentsChars[segmentCount] : defaultSeparator; >+ newChars[charCount + segmentCount++] = separator; >+ } >+ return new String(newChars, 0, newChars.length); >+} > > /** > * Returns a <code>Point</code> whose x coordinate is the >@@ -836,6 +1041,15 @@ > start [0] = mbcsToWcsPos (start [0]); > end [0] = mbcsToWcsPos (end [0]); > } >+ if (segments != null) { >+ if (start[0] == end[0]) { >+ start [0] = end [0] = untranslateOffset (start [0]); >+ } >+ else { >+ start [0] = untranslateOffset (start [0]); >+ end [0] = untranslateOffset (end [0]); >+ } >+ } > return new Point (start [0], end [0]); > } > >@@ -874,6 +1088,9 @@ > if (length == 0) return ""; > TCHAR buffer = new TCHAR (getCodePage (), length + 1); > OS.GetWindowText (handle, buffer, length + 1); >+ if (segments != null) { >+ return deprocessText(buffer.toString (0, length), segments); >+ } > return buffer.toString (0, length); > } > >@@ -918,7 +1135,10 @@ > checkWidget (); > int /*long*/ hwndText = OS.GetDlgItem (handle, CBID_EDIT); > if (hwndText == 0) return LIMIT; >- return (int)/*64*/OS.SendMessage (hwndText, OS.EM_GETLIMITTEXT, 0, 0) & 0x7FFFFFFF; >+ int/*64*/ limit = (int)/*64*/OS.SendMessage (hwndText, OS.EM_GETLIMITTEXT, 0, 0) & 0x7FFFFFFF; >+ // XXX default limit is 0xfffffffE on NT, probably depends on control style >+ if (segments != null && limit < LIMIT) limit = Math.max(1, limit - segments.length); >+ return limit; > } > > /** >@@ -1024,6 +1244,24 @@ > return index; > } > >+void insertItemSegments(int[] segments, int index) { >+ if (segments == null) return; >+ int count = (int)/*64*/OS.SendMessage (handle, OS.CB_GETCOUNT, 0, 0); >+ if (index >= count) return; >+ if (itemSegments == null) itemSegments = new int[count + 4][]; >+ else { >+ int[][] newSegments = new int[Math.max(itemSegments.length, count + 4)][]; >+ if (index > 0) { >+ System.arraycopy(itemSegments, 0, newSegments, 0, index); >+ } >+ if (index < count) { >+ System.arraycopy(itemSegments, index, newSegments, index + 1, count - index); >+ } >+ itemSegments = newSegments; >+ } >+ itemSegments[index] = segments; >+} >+ > int mbcsToWcsPos (int mbcsPos) { > if (mbcsPos <= 0) return 0; > if (OS.IsUnicode) return mbcsPos; >@@ -1240,6 +1478,16 @@ > if ((style & SWT.H_SCROLL) != 0) setScrollWidth (0); > } > >+void removeItemSegments(int index) { >+ if (index < 0 || itemSegments == null) return; >+ int count = itemSegments.length; >+ if (index < count - 1) { >+ System.arraycopy(itemSegments, index + 1, itemSegments, index, count - index - 1); >+ } else if (index == count - 1) { >+ itemSegments[index] = null; >+ } >+} >+ > /** > * Removes the listener from the collection of listeners who will > * be notified when the receiver's text is modified. >@@ -1266,6 +1514,31 @@ > > /** > * Removes the listener from the collection of listeners who will >+ * be notified when the receiver's text is modified. >+ * >+ * @param listener the listener which should no longer be notified >+ * >+ * @exception IllegalArgumentException <ul> >+ * <li>ERROR_NULL_ARGUMENT - if the listener is null</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> >+ * >+ * @see SegmentListener >+ * @see #addSegmentListener >+ */ >+public void removeSegmentListener(SegmentListener listener) { >+ checkWidget(); >+ if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); >+ clearSegments(true); >+ eventTable.unhook (SWT.GetSegments, listener); >+ applySegments(); >+ applyItemsSegments(); >+} >+/** >+ * Removes the listener from the collection of listeners who will > * be notified when the user changes the receiver's selection. > * > * @param listener the listener which should no longer be notified >@@ -1783,6 +2056,15 @@ > start = wcsToMbcsPos (start); > end = wcsToMbcsPos (end); > } >+ if (segments != null) { >+ if (start == end) { >+ start = end = translateOffset (start); >+ } >+ else { >+ start = translateOffset (start); >+ end = translateOffset (end); >+ } >+ } > int /*long*/ bits = OS.MAKELPARAM (start, end); > OS.SendMessage (handle, OS.CB_SETEDITSEL, 0, bits); > } >@@ -1815,6 +2097,7 @@ > public void setText (String string) { > checkWidget (); > if (string == null) error (SWT.ERROR_NULL_ARGUMENT); >+ if (segments != null) clearSegments(false); > if ((style & SWT.READ_ONLY) != 0) { > int index = indexOf (string); > if (index != -1) select (index); >@@ -1828,6 +2111,9 @@ > if (string.length () > limit) string = string.substring (0, limit); > TCHAR buffer = new TCHAR (getCodePage (), string, true); > if (OS.SetWindowText (handle, buffer)) { >+ if (hooks(SWT.GetSegments) || filters(SWT.GetSegments)) { >+ applySegments(); >+ } > sendEvent (SWT.Modify); > // widget could be disposed at this point > } >@@ -1856,7 +2142,11 @@ > public void setTextLimit (int limit) { > checkWidget (); > if (limit == 0) error (SWT.ERROR_CANNOT_BE_ZERO); >- OS.SendMessage (handle, OS.CB_LIMITTEXT, limit, 0); >+ if (segments != null && limit > 0) { >+ OS.SendMessage (handle, OS.CB_LIMITTEXT, limit + Math.min(segments.length, LIMIT - limit), 0); >+ } else { >+ OS.SendMessage (handle, OS.CB_LIMITTEXT, limit, 0); >+ } > } > > void setToolTipText (Shell shell, String string) { >@@ -1904,6 +2194,14 @@ > } > } > >+int translateOffset(int offset) { >+ if (segments == null) return offset; >+ for (int i = 0, nSegments = segments.length; i < nSegments && offset - i >= segments[i]; i++) { >+ offset++; >+ } >+ return offset; >+} >+ > boolean translateTraversal (MSG msg) { > /* > * When the combo box is dropped down, allow return >@@ -1954,6 +2252,14 @@ > } > } > >+int untranslateOffset(int offset) { >+ if (segments == null) return offset; >+ for (int i = 0, nSegments = segments.length; i < nSegments && offset > segments[i]; i++) { >+ offset--; >+ } >+ return offset; >+} >+ > void updateDropDownHeight () { > /* > * Feature in Windows. If the combo box has the CBS_DROPDOWN >@@ -2044,11 +2350,30 @@ > int /*long*/ hwndList = OS.GetDlgItem (handle, CBID_LIST); > if ((hwndText != 0 && hwnd == hwndText) || (hwndList != 0 && hwnd == hwndList)) { > LRESULT result = null; >+ boolean processSegments = false, redraw = false; > switch (msg) { > /* Keyboard messages */ >- case OS.WM_CHAR: result = wmChar (hwnd, wParam, lParam); break; >+ case OS.WM_CHAR: >+ if ((hooks(SWT.GetSegments) || filters(SWT.GetSegments)) >+ && OS.GetKeyState(OS.VK_CONTROL) >= 0 >+ && OS.GetKeyState(OS.VK_MENU) >= 0) { >+ processSegments = !ignoreCharacter; >+ } >+ result = wmChar (hwnd, wParam, lParam); break; > case OS.WM_IME_CHAR: result = wmIMEChar (hwnd, wParam, lParam); break; >- case OS.WM_KEYDOWN: result = wmKeyDown (hwnd, wParam, lParam); break; >+ case OS.WM_KEYDOWN: >+ if (hooks(SWT.GetSegments) || filters(SWT.GetSegments)) { >+ switch (wParam) { >+ case OS.VK_DELETE: >+ processSegments = true; >+ break; >+ case OS.VK_RIGHT: >+ case OS.VK_LEFT: >+ processSegments = segments != null && OS.GetKeyState(OS.VK_MENU) >= 0; >+ break; >+ } >+ } >+ result = wmKeyDown (hwnd, wParam, lParam); break; > case OS.WM_KEYUP: result = wmKeyUp (hwnd, wParam, lParam); break; > case OS.WM_SYSCHAR: result = wmSysChar (hwnd, wParam, lParam); break; > case OS.WM_SYSKEYDOWN: result = wmSysKeyDown (hwnd, wParam, lParam); break; >@@ -2080,9 +2405,14 @@ > case OS.WM_CONTEXTMENU: result = wmContextMenu (hwnd, wParam, lParam); break; > > /* Clipboard messages */ >+ case OS.WM_COPY: { >+ processSegments = segments != null; >+ break; >+ } > case OS.WM_CLEAR: > case OS.WM_CUT: > case OS.WM_PASTE: >+ processSegments = hooks(SWT.GetSegments) || filters(SWT.GetSegments); > case OS.WM_UNDO: > case OS.EM_UNDO: > case OS.WM_SETTEXT: >@@ -2092,33 +2422,115 @@ > break; > } > if (result != null) return result.value; >+ >+ if (processSegments) { >+ if (getDrawing () && OS.IsWindowVisible (hwndText)) { >+ redraw = true; >+ OS.DefWindowProc (hwndText, OS.WM_SETREDRAW, 0, 0); >+ } >+ clearSegments(true); >+ int code = callWindowProc (hwnd, msg, wParam, lParam); >+ applySegments(); >+ if (redraw) { >+ OS.DefWindowProc (hwndText, OS.WM_SETREDRAW, 1, 0); >+ if (OS.IsWinCE) { >+ OS.InvalidateRect (hwndText, null, true); >+ } else { >+ OS.RedrawWindow (hwndText, null, 0, OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE); >+ } >+ } >+ return code; >+ } > return callWindowProc (hwnd, msg, wParam, lParam); > } > } >- if (msg == OS.CB_SETCURSEL) { >- if ((style & SWT.READ_ONLY) != 0) { >- if (hooks (SWT.Verify) || filters (SWT.Verify)) { >- String oldText = getText (), newText = null; >- if (wParam == -1) { >- newText = ""; >- } else { >- if (0 <= wParam && wParam < getItemCount ()) { >- newText = getItem ((int)/*64*/wParam); >+ switch (msg) { >+ case OS.CB_SETCURSEL: { >+ int code; >+ if ((style & SWT.READ_ONLY) != 0) { >+ if (hooks (SWT.Verify) || filters (SWT.Verify)) { >+ String oldText = getText (), newText = null; >+ if (wParam == -1) { >+ newText = ""; >+ } else { >+ if (0 <= wParam && wParam < getItemCount ()) { >+ newText = getItem ((int)/*64*/wParam); >+ } > } >- } >- if (newText != null && !newText.equals (oldText)) { >- int length = OS.GetWindowTextLength (handle); >- oldText = newText; >- newText = verifyText (newText, 0, length, null); >- if (newText == null) return 0; >- if (!newText.equals (oldText)) { >- int index = indexOf (newText); >- if (index != -1 && index != wParam) { >- return callWindowProc (handle, OS.CB_SETCURSEL, index, lParam); >+ if (newText != null && !newText.equals (oldText)) { >+ int length = OS.GetWindowTextLength (handle); >+ oldText = newText; >+ newText = verifyText (newText, 0, length, null); >+ if (newText == null) return 0; >+ if (!newText.equals (oldText)) { >+ int index = indexOf (newText); >+ if (index != -1 && index != wParam) { >+ code = callWindowProc (handle, OS.CB_SETCURSEL, index, lParam); >+ if (code != OS.CB_ERR) { >+ if (itemSegments != null && itemSegments.length > code) { >+ segments = itemSegments[code]; >+ } else { >+ segments = null; >+ } >+ } >+ return code; >+ } > } > } > } > } >+ code = super.windowProc (hwnd, msg, wParam, lParam); >+ if (code == wParam) { >+ if (itemSegments != null && itemSegments.length > code) { >+ segments = itemSegments[code]; >+ } else { >+ segments = null; >+ } >+ } >+ return code; >+ } >+ case OS.CB_ADDSTRING: >+ case OS.CB_INSERTSTRING: >+ case OS.CB_FINDSTRINGEXACT: { >+ // XXX For CB_FINDSTRINGEXACT a neater approach is probably to >+ // normalize items rather than process the search key >+ if (lParam != 0) { >+ int length = OS.IsUnicode ? OS.wcslen(lParam) : OS.strlen(lParam); >+ TCHAR buffer = new TCHAR (getCodePage (), length); >+ OS.MoveMemory(buffer, lParam, buffer.length() * TCHAR.sizeof); >+ String string = buffer.toString (0, length); >+ Event event = getSegments(string); >+ if (event != null && event.segments != null) { >+ buffer = new TCHAR (getCodePage(), getSegmentsText(string, event), true); >+ int /*long*/ hHeap = OS.GetProcessHeap (); >+ length = buffer.length() * TCHAR.sizeof; >+ int /*long*/ pszText = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, length); >+ OS.MoveMemory (pszText, buffer, length); >+ int code = super.windowProc (hwnd, msg, wParam, pszText); >+ OS.HeapFree (hHeap, 0, pszText); >+ if (msg == OS.CB_FINDSTRINGEXACT) return code; >+ if (code != OS.CB_ERR && code != OS.CB_ERRSPACE) { >+ insertItemSegments(event.segments, code); >+ } >+ return code; >+ } >+ } >+ break; >+ } >+ case OS.CB_DELETESTRING: { >+ int code = super.windowProc (hwnd, msg, wParam, lParam); >+ if (code != OS.CB_ERR && code != OS.CB_ERRSPACE) removeItemSegments(wParam); >+ return code; >+ } >+ case OS.CB_RESETCONTENT: { >+ segments = null; >+ if (itemSegments != null) { >+ int count = itemSegments.length; >+ while (count-- > 0) { >+ itemSegments[count] = null; >+ } >+ } >+ break; > } > } > return super.windowProc (hwnd, msg, wParam, lParam); >@@ -2478,6 +2890,8 @@ > } > OS.SetWindowLong (hwnd, OS.GWL_EXSTYLE, bits1); > OS.SetWindowLong (hwnd, OS.GWL_STYLE, bits2); >+ } else if (hooks(SWT.GetSegments) || filters(SWT.GetSegments)) { >+ applySegments(); > } > break; > } >Index: JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_Text.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_Text.java,v >retrieving revision 1.30 >diff -u -r1.30 Test_org_eclipse_swt_widgets_Text.java >--- JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_Text.java 18 Mar 2009 18:39:02 -0000 1.30 >+++ JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_Text.java 10 Sep 2010 14:42:03 -0000 >@@ -1387,6 +1387,7 @@ > methodNames.addElement("test_consistency_Modify"); > methodNames.addElement("test_consistency_MenuDetect"); > methodNames.addElement("test_consistency_DragDetect"); >+ methodNames.addElement("test_consistency_Segments"); > methodNames.addAll(Test_org_eclipse_swt_widgets_Scrollable.methodNames()); // add superclass method names > return methodNames; > } >@@ -1444,6 +1445,7 @@ > else if (getName().equals("test_consistency_Modify")) test_consistency_Modify(); > else if (getName().equals("test_consistency_MenuDetect")) test_consistency_MenuDetect(); > else if (getName().equals("test_consistency_DragDetect")) test_consistency_DragDetect(); >+ else if (getName().equals("test_consistency_Segments")) test_consistency_Segments(); > else super.runTest(); > } > >@@ -1498,4 +1500,118 @@ > consistencyEvent(30, 10, 50, 0, ConsistencyUtility.MOUSE_DRAG); > } > >+public void test_consistency_Segments () { >+ final SegmentListener sl1 = new SegmentListener() { >+ public void lineGetSegments(SegmentEvent event) { >+ if ((event.text.length() & 1) == 1) { >+ event.segments = new int [] {1, event.text.length()}; >+ event.segmentsChars = new char [] {'<', '>'}; >+ } else { >+ event.segments = new int [] {0, 0, event.text.length()}; >+ event.segmentsChars = new char [] {':', '<', '>'}; >+ } >+ listenerCalled = true; >+ } >+ }; >+ try { >+ text.addSegmentListener(null); >+ fail("No exception thrown for addSegmentListener(null)"); >+ } >+ catch (IllegalArgumentException e) { >+ } >+ listenerCalled = false; >+ >+ //doSegmentsTest(false); >+ >+ text.addSegmentListener(sl1); >+ assertTrue(listenerCalled); >+ listenerCalled = false; >+ doSegmentsTest(true); >+ >+ text.addSegmentListener(sl1); >+ assertTrue(listenerCalled); >+ listenerCalled = false; >+ doSegmentsTest(true); >+ >+ text.removeSegmentListener(sl1); >+ assertTrue(listenerCalled); >+ listenerCalled = false; >+ doSegmentsTest(true); >+ >+ text.removeSegmentListener(sl1); >+ assertTrue(!listenerCalled); >+ doSegmentsTest(false); >+} >+ >+private void doSegmentsTest (boolean isListening) { >+ String string = "123456"; >+ >+ // Test setText >+ text.setText(string); >+ assertEquals(isListening, listenerCalled); >+ listenerCalled = false; >+ assertEquals(string, text.getText()); >+ >+ // Test limit >+ text.setTextLimit(-1); >+ text.setText(string); >+ assertEquals(string, text.getText()); >+ >+ int limit = string.length() - 1; >+ text.setTextLimit(limit); >+ assertEquals(limit, text.getTextLimit()); >+ text.setText(string); >+ assertEquals(string.substring(0, limit), text.getText()); >+ >+ text.setTextLimit(Text.LIMIT); >+ text.setText(string); >+ assertEquals(string, text.getText()); >+ assertEquals(Text.LIMIT, text.getTextLimit()); >+ >+ // Test selection, copy and paste >+ listenerCalled = false; >+ Point pt = new Point(1, 3); >+ text.setSelection(pt); >+ assertEquals(pt, text.getSelection()); >+ assertFalse(listenerCalled); >+ text.copy(); >+ assertEquals(isListening, listenerCalled); >+ listenerCalled = false; >+ >+ text.setSelection(new Point(0, 0)); >+ text.paste(); >+ assertEquals(isListening, listenerCalled); >+ listenerCalled = false; >+ >+ String substr = string.substring(pt.x, pt.y); >+ assertEquals(substr + string, text.getText()); >+ assertEquals(new Point(pt.y - pt.x, pt.y - pt.x), text.getSelection()); >+ >+ // Test cut >+ text.setSelection(new Point(0, 2)); >+ assertEquals(substr, text.getSelectionText()); >+ text.cut(); >+ assertEquals(isListening, listenerCalled); >+ listenerCalled = false; >+ assertEquals(string, text.getText()); >+ >+ // Test append >+ substr = "56"; >+ text.append(substr); >+ assertEquals(isListening, listenerCalled); >+ listenerCalled = false; >+ assertEquals(string + substr, text.getText()); >+ >+ // Test insert >+ substr = "12"; >+ text.setSelection(6, 8); >+ text.cut(); >+ listenerCalled = false; >+ text.setSelection(0, 0); >+ text.insert(substr); >+ assertEquals(isListening, listenerCalled); >+ listenerCalled = false; >+ assertEquals(substr + string, text.getText()); >+} >+ > } >Index: JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_Combo.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_Combo.java,v >retrieving revision 1.21 >diff -u -r1.21 Test_org_eclipse_swt_widgets_Combo.java >--- JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_Combo.java 18 Mar 2009 18:39:02 -0000 1.21 >+++ JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_Combo.java 10 Sep 2010 14:41:02 -0000 >@@ -216,10 +216,10 @@ > combo.copy(); > combo.setSelection(new Point(0,0)); > combo.paste(); >- assertTrue(":a:", combo.getText().equals("23123456")); >+ assertTrue(":a:" + combo.getText(), combo.getText().equals("23123456")); > } > >-public void test_cut() { >+public void test_cut() { > combo.setText("123456"); > combo.setSelection(new Point(1,3)); > combo.cut(); >@@ -825,6 +825,7 @@ > methodNames.addElement("test_consistency_EnterSelection"); > methodNames.addElement("test_consistency_MenuDetect"); > methodNames.addElement("test_consistency_DragDetect"); >+ methodNames.addElement("test_Segments"); > methodNames.addAll(Test_org_eclipse_swt_widgets_Composite.methodNames()); // add superclass method names > return methodNames; > } >@@ -838,6 +839,7 @@ > else if (getName().equals("test_computeSizeIIZ")) test_computeSizeIIZ(); > else if (getName().equals("test_copy")) test_copy(); > else if (getName().equals("test_cut")) test_cut(); >+ else if (getName().equals("test_Segments")) test_Segments(); > else if (getName().equals("test_deselectAll")) test_deselectAll(); > else if (getName().equals("test_deselectI")) test_deselectI(); > else if (getName().equals("test_getItemCount")) test_getItemCount(); >@@ -954,6 +956,133 @@ > consistencyEvent(10, 5, 20, 10, ConsistencyUtility.MOUSE_DRAG); > } > >+public void test_Segments () { >+ final SegmentListener sl1 = new SegmentListener() { >+ public void lineGetSegments(SegmentEvent event) { >+ if ((event.text.length() & 1) == 1) { >+ event.segments = new int [] {1, event.text.length()}; >+ event.segmentsChars = new char [] {'<', '>'}; >+ } else { >+ event.segments = new int [] {0, 0, event.text.length()}; >+ event.segmentsChars = new char [] {':', '<', '>'}; >+ } >+ listenerCalled = true; >+ } >+ }; >+ try { >+ combo.addSegmentListener(null); >+ fail("No exception thrown for addSegmentListener(null)"); >+ } >+ catch (IllegalArgumentException e) { >+ } >+ listenerCalled = false; >+ >+ //doSegmentsTest(false); >+ >+ combo.addSegmentListener(sl1); >+ assertTrue(listenerCalled); >+ listenerCalled = false; >+ doSegmentsTest(true); >+ >+ combo.addSegmentListener(sl1); >+ assertTrue(listenerCalled); >+ listenerCalled = false; >+ doSegmentsTest(true); >+ >+ combo.removeSegmentListener(sl1); >+ assertTrue(listenerCalled); >+ listenerCalled = false; >+ doSegmentsTest(true); >+ >+ combo.removeSegmentListener(sl1); >+ assertTrue(!listenerCalled); >+ doSegmentsTest(false); >+} >+ >+private void doSegmentsTest (boolean isListening) { >+ String[] items = { "1.", "2a..", "2.." }; >+ String string = "123456"; >+ >+ // Test setItems >+ combo.setItems(items); >+ assertEquals(isListening, listenerCalled); >+ listenerCalled = false; >+ assertEquals(items, combo.getItems()); >+ >+ // Test setText >+ combo.setText(string); >+ assertEquals(isListening, listenerCalled); >+ listenerCalled = false; >+ assertEquals(string, combo.getText()); >+ >+ // Test getItem, indexOf, select >+ int count = items.length; >+ for (int i = 0; i < count; i++) { >+ assertEquals(items[i], combo.getItem(i)); >+ assertFalse(listenerCalled); >+ assertEquals(i, combo.indexOf(items[i])); >+ assertEquals(isListening, listenerCalled); >+ listenerCalled = false; >+ >+ combo.select(i); >+ assertEquals(items[i], combo.getText()); >+ assertFalse(listenerCalled); >+ } > >+ for (int i = 0; i < count; i++) { >+ combo.setText(combo.getItem(i)); >+ assertEquals(items[i], combo.getText()); >+ } >+ listenerCalled = false; >+ >+ // Test limit >+ combo.setTextLimit(-1); >+ combo.setText(string); >+ assertEquals(string, combo.getText()); >+ >+ int limit = string.length() - 1; >+ combo.setTextLimit(limit); >+ assertEquals(limit, combo.getTextLimit()); >+ combo.setText(string); >+ assertEquals(string.substring(0, limit), combo.getText()); >+ >+ combo.setTextLimit(Combo.LIMIT); >+ combo.setText(string); >+ assertEquals(string, combo.getText()); >+ >+ // Test add item >+ String item = "3..."; >+ combo.add(item); >+ assertEquals(isListening, listenerCalled); >+ listenerCalled = false; >+ assertEquals(item, combo.getItem(count++)); >+ >+ // Test remove item by name >+ combo.remove(items[1]); >+ assertEquals(--count, combo.getItemCount()); >+ assertEquals(1, combo.indexOf(items[2])); >+ >+ combo.setTextLimit(Combo.LIMIT); >+ combo.setText(string); >+ >+ // Test copy and paste >+ combo.setSelection(new Point(1,3)); >+ combo.copy(); >+ assertEquals(isListening, listenerCalled); >+ listenerCalled = false; >+ >+ combo.setSelection(new Point(0,0)); >+ combo.paste(); >+ assertEquals(isListening, listenerCalled); >+ listenerCalled = false; >+ assertEquals(string.substring(1, 3) + string, combo.getText()); >+ >+ // Test cut >+ combo.setSelection(new Point(0,2)); >+ combo.cut(); >+ assertEquals(isListening, listenerCalled); >+ listenerCalled = false; >+ assertEquals(string, combo.getText()); >+} > > }
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 230854
:
105752
|
157717
|
158504
|
158513
|
158881
|
158882
|
159820
|
160175
|
160176
|
160483
|
160652
|
160692
|
160693
|
160984
|
161174
|
162293
|
163180
|
178628
|
178635
|
179537
|
179540
|
179583
|
180564
|
185633
|
188252
|
188611
|
188635
|
191558
|
191583
|
191823
|
191860
|
193759
|
194112
|
204679
|
204835
|
204836