]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Text.java
Remove invalid SHA-256-Digests
[simantics/platform.git] / bundles / org.eclipse.swt.win32.win32.x86_64 / src / org / eclipse / swt / widgets / Text.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2016 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.swt.widgets;
15
16
17 import java.util.*;
18
19 import org.eclipse.swt.*;
20 import org.eclipse.swt.events.*;
21 import org.eclipse.swt.graphics.*;
22 import org.eclipse.swt.internal.*;
23 import org.eclipse.swt.internal.win32.*;
24
25 /**
26  * Instances of this class are selectable user interface
27  * objects that allow the user to enter and modify text.
28  * Text controls can be either single or multi-line.
29  * When a text control is created with a border, the
30  * operating system includes a platform specific inset
31  * around the contents of the control.  When created
32  * without a border, an effort is made to remove the
33  * inset such that the preferred size of the control
34  * is the same size as the contents.
35  * <dl>
36  * <dt><b>Styles:</b></dt>
37  * <dd>CENTER, ICON_CANCEL, ICON_SEARCH, LEFT, MULTI, PASSWORD, SEARCH, SINGLE, RIGHT, READ_ONLY, WRAP</dd>
38  * <dt><b>Events:</b></dt>
39  * <dd>DefaultSelection, Modify, Verify, OrientationChange</dd>
40  * </dl>
41  * <p>
42  * Note: Only one of the styles MULTI and SINGLE may be specified,
43  * and only one of the styles LEFT, CENTER, and RIGHT may be specified.
44  * </p>
45  * <p>
46  * Note: The styles ICON_CANCEL and ICON_SEARCH are hints used in combination with SEARCH.
47  * When the platform supports the hint, the text control shows these icons.  When an icon
48  * is selected, a default selection event is sent with the detail field set to one of
49  * ICON_CANCEL or ICON_SEARCH.  Normally, application code does not need to check the
50  * detail.  In the case of ICON_CANCEL, the text is cleared before the default selection
51  * event is sent causing the application to search for an empty string.
52  * </p>
53  * <p>
54  * Note: Some text actions such as Undo are not natively supported on all platforms.
55  * </p>
56  * <p>
57  * IMPORTANT: This class is <em>not</em> intended to be subclassed.
58  * </p>
59  *
60  * @see <a href="http://www.eclipse.org/swt/snippets/#text">Text snippets</a>
61  * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
62  * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
63  * @noextend This class is not intended to be subclassed by clients.
64  */
65 public class Text extends Scrollable {
66         int tabs, oldStart, oldEnd;
67         boolean doubleClick, ignoreModify, ignoreVerify, ignoreCharacter, allowPasswordChar;
68         String message;
69         int[] segments;
70         int clearSegmentsCount = 0;
71         long hwndSearch, hwndCancel, hwndActive;
72
73         static final char LTR_MARK = '\u200e';
74         static final char RTL_MARK = '\u200f';
75
76         /* Custom icons defined in swt.rc */
77         static final int IDI_SEARCH = 101;
78         static final int IDI_CANCEL = 102;
79
80         /**
81         * The maximum number of characters that can be entered
82         * into a text widget.
83         * <p>
84         * Note that this value is platform dependent, based upon
85         * the native widget implementation.
86         * </p>
87         */
88         public static final int LIMIT;
89
90         /**
91         * The delimiter used by multi-line text widgets.  When text
92         * is queried and from the widget, it will be delimited using
93         * this delimiter.
94         */
95         public static final String DELIMITER;
96
97         /*
98         * This code is intentionally commented.
99         */
100 //      static final char PASSWORD;
101
102         /*
103         * These values can be different on different platforms.
104         * Therefore they are not initialized in the declaration
105         * to stop the compiler from inlining.
106         */
107         static {
108                 LIMIT = 0x7FFFFFFF;
109                 DELIMITER = "\r\n";
110         }
111
112         static final long EditProc;
113         static final TCHAR EditClass = new TCHAR (0, "EDIT", true);
114         static {
115                 WNDCLASS lpWndClass = new WNDCLASS ();
116                 OS.GetClassInfo (0, EditClass, lpWndClass);
117                 EditProc = lpWndClass.lpfnWndProc;
118                 /*
119                 * This code is intentionally commented.
120                 */
121 //              long hwndText = OS.CreateWindowEx (0,
122 //                      EditClass,
123 //                      null,
124 //                      OS.WS_OVERLAPPED | OS.ES_PASSWORD,
125 //                      0, 0, 0, 0,
126 //                      0,
127 //                      0,
128 //                      OS.GetModuleHandle (null),
129 //                      null);
130 //              char echo = (char) OS.SendMessage (hwndText, OS.EM_GETPASSWORDCHAR, 0, 0);
131 //              OS.DestroyWindow (hwndText);
132 //              PASSWORD = echo != 0 ? echo : '*';
133         }
134
135 /**
136  * Constructs a new instance of this class given its parent
137  * and a style value describing its behavior and appearance.
138  * <p>
139  * The style value is either one of the style constants defined in
140  * class <code>SWT</code> which is applicable to instances of this
141  * class, or must be built by <em>bitwise OR</em>'ing together
142  * (that is, using the <code>int</code> "|" operator) two or more
143  * of those <code>SWT</code> style constants. The class description
144  * lists the style constants that are applicable to the class.
145  * Style bits are also inherited from superclasses.
146  * </p>
147  *
148  * @param parent a composite control which will be the parent of the new instance (cannot be null)
149  * @param style the style of control to construct
150  *
151  * @exception IllegalArgumentException <ul>
152  *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
153  * </ul>
154  * @exception SWTException <ul>
155  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
156  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
157  * </ul>
158  *
159  * @see SWT#SINGLE
160  * @see SWT#MULTI
161  * @see SWT#READ_ONLY
162  * @see SWT#WRAP
163  * @see SWT#LEFT
164  * @see SWT#RIGHT
165  * @see SWT#CENTER
166  * @see SWT#PASSWORD
167  * @see SWT#SEARCH
168  * @see SWT#ICON_SEARCH
169  * @see SWT#ICON_CANCEL
170  * @see Widget#checkSubclass
171  * @see Widget#getStyle
172  */
173 public Text (Composite parent, int style) {
174         super (parent, checkStyle (style));
175 }
176
177 @Override
178 long callWindowProc (long hwnd, int msg, long wParam, long lParam) {
179         if (handle == 0) return 0;
180         boolean redraw = false;
181         switch (msg) {
182                 case OS.WM_ERASEBKGND: {
183                         if (findImageControl () != null) return 0;
184                         break;
185                 }
186                 case OS.WM_HSCROLL:
187                 case OS.WM_VSCROLL: {
188                         redraw = findImageControl () != null && getDrawing () && OS.IsWindowVisible (handle);
189                         if (redraw) OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
190                         break;
191                 }
192                 case OS.WM_PAINT: {
193                         boolean doubleBuffer = findImageControl () != null;
194                         boolean drawMessage = false;
195                         if ((style & SWT.SINGLE) != 0 && (style & SWT.READ_ONLY) != 0 && message.length () > 0 ) {
196                                 drawMessage = hwnd != OS.GetFocus () && OS.GetWindowTextLength (handle) == 0;
197                         }
198                         if (doubleBuffer || drawMessage) {
199                                 long paintDC = 0;
200                                 PAINTSTRUCT ps = new PAINTSTRUCT ();
201                                 paintDC = OS.BeginPaint (handle, ps);
202                                 int width = ps.right - ps.left;
203                                 int height = ps.bottom - ps.top;
204                                 if (width != 0 && height != 0) {
205                                         long hDC = paintDC, hBitmap = 0, hOldBitmap = 0;
206                                         POINT lpPoint1 = null, lpPoint2 = null;
207                                         if (doubleBuffer) {
208                                                 hDC = OS.CreateCompatibleDC (paintDC);
209                                                 lpPoint1 = new POINT ();
210                                                 lpPoint2 = new POINT ();
211                                                 OS.SetWindowOrgEx (hDC, ps.left, ps.top, lpPoint1);
212                                                 OS.SetBrushOrgEx (hDC, ps.left, ps.top, lpPoint2);
213                                                 hBitmap = OS.CreateCompatibleBitmap (paintDC, width, height);
214                                                 hOldBitmap = OS.SelectObject (hDC, hBitmap);
215                                                 RECT rect = new RECT ();
216                                                 OS.SetRect (rect, ps.left, ps.top, ps.right, ps.bottom);
217                                                 drawBackground (hDC, rect);
218                                         }
219
220                                         OS.CallWindowProc (EditProc, hwnd, OS.WM_PAINT, hDC, lParam);
221                                         /*
222                                         * Bug in Windows.  Windows does not draw the cue message when the Edit
223                                         * control is read-only. The fix is to draw the cue messages ourselves.
224                                         */
225                                         if (drawMessage) {
226                                                 RECT rect = new RECT();
227                                                 OS.GetClientRect(handle, rect);
228                                                 long margins = OS.SendMessage (handle, OS.EM_GETMARGINS, 0, 0);
229                                                 rect.left += OS.LOWORD (margins);
230                                                 rect.right -= OS.HIWORD (margins);
231                                                 if ((style & SWT.BORDER) != 0) {
232                                                         rect.left++;
233                                                         rect.top++;
234                                                         rect.right--;
235                                                         rect.bottom--;
236                                                 }
237                                                 char [] buffer = message.toCharArray ();
238                                                 int uFormat = OS.DT_EDITCONTROL;
239                                                 boolean rtl = (style & SWT.RIGHT_TO_LEFT) != 0;
240                                                 if (rtl) uFormat |= OS.DT_RTLREADING;
241                                                 int alignment = style & (SWT.LEFT | SWT.CENTER | SWT.RIGHT);
242                                                 switch (alignment) {
243                                                         case SWT.LEFT: uFormat |= (rtl ? OS.DT_RIGHT : OS.DT_LEFT); break;
244                                                         case SWT.CENTER: uFormat |= OS.DT_CENTER;
245                                                         case SWT.RIGHT: uFormat |= (rtl ? OS.DT_LEFT : OS.DT_RIGHT); break;
246                                                 }
247                                                 long hFont = OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0);
248                                                 long hOldFont = OS.SelectObject (hDC, hFont);
249                                                 OS.SetTextColor (hDC, OS.GetSysColor (OS.COLOR_GRAYTEXT));
250                                                 OS.SetBkMode (hDC, OS.TRANSPARENT);
251                                                 OS.DrawText (hDC, buffer, buffer.length, rect, uFormat);
252                                                 OS.SelectObject (hDC, hOldFont);
253                                         }
254
255                                         if (doubleBuffer) {
256                                                 OS.SetWindowOrgEx (hDC, lpPoint1.x, lpPoint1.y, null);
257                                                 OS.SetBrushOrgEx (hDC, lpPoint2.x, lpPoint2.y, null);
258                                                 OS.BitBlt (paintDC, ps.left, ps.top, width, height, hDC, 0, 0, OS.SRCCOPY);
259                                                 OS.SelectObject (hDC, hOldBitmap);
260                                                 OS.DeleteObject (hBitmap);
261                                                 OS.DeleteObject (hDC);
262                                         }
263                                 }
264                                 OS.EndPaint (handle, ps);
265                                 return 0;
266                         }
267                         break;
268                 }
269         }
270         if ((style & SWT.SEARCH) != 0) {
271                 switch (msg) {
272                         case OS.WM_MOUSEMOVE: {
273                                 POINT pt = new POINT ();
274                                 OS.POINTSTOPOINT(pt, lParam);
275                                 long prevActive = hwndActive;
276                                 hwndActive = OS.ChildWindowFromPointEx (handle, pt, OS.CWP_SKIPINVISIBLE);
277                                 if (hwndActive == handle) hwndActive = 0;
278                                 if (prevActive != hwndActive) {
279                                         if (prevActive != 0) OS.InvalidateRect (prevActive, null, false);
280                                         if (hwndActive != 0) OS.InvalidateRect (hwndActive, null, false);
281                                 }
282                                 break;
283                         }
284                         case OS.WM_MOUSELEAVE:
285                                 if (hwndActive != 0) {
286                                         OS.InvalidateRect (hwndActive, null, false);
287                                         hwndActive = 0;
288                                 }
289                                 break;
290                         case OS.WM_LBUTTONDOWN:
291                                 if (hwndActive != 0) {
292                                         OS.InvalidateRect (hwndActive, null, false);
293                                         return 0; // prevent mouse selection
294                                 }
295                                 break;
296                         case OS.WM_LBUTTONUP: {
297                                 if (hwndActive != 0) {
298                                         Event e = new Event();
299                                         if (hwndActive == hwndSearch) {
300                                                 e.detail = SWT.ICON_SEARCH;
301                                         } else {
302                                                 e.detail = SWT.ICON_CANCEL;
303                                                 setText ("");
304                                         }
305                                         setFocus ();
306                                         selectAll ();
307                                         sendSelectionEvent (SWT.DefaultSelection, e, false);
308                                 }
309                                 break;
310                         }
311                 }
312         }
313         long code = OS.CallWindowProc (EditProc, hwnd, msg, wParam, lParam);
314         switch (msg) {
315                 case OS.WM_HSCROLL:
316                 case OS.WM_VSCROLL: {
317                         if (redraw) {
318                                 OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
319                                 OS.InvalidateRect (handle, null, true);
320                         }
321                         break;
322                 }
323         }
324         return code;
325 }
326
327 @Override
328 void createHandle () {
329         super.createHandle ();
330         OS.SendMessage (handle, OS.EM_LIMITTEXT, 0, 0);
331         if ((style & SWT.READ_ONLY) != 0) {
332                 if (applyThemeBackground () == 1) {
333                         state |= THEME_BACKGROUND;
334                 }
335         }
336         if ((style & SWT.SEARCH) != 0) {
337                 if (display.hIconSearch == 0) {
338                         long [] phicon = new long [1];
339                         int hresult = OS.LoadIconMetric (OS.GetLibraryHandle (), IDI_SEARCH, OS.LIM_SMALL, phicon);
340                         if (hresult != OS.S_OK) error (SWT.ERROR_NO_HANDLES);
341                         display.hIconSearch = phicon [0];
342                         hresult = OS.LoadIconMetric (OS.GetLibraryHandle (), IDI_CANCEL, OS.LIM_SMALL, phicon);
343                         if (hresult != OS.S_OK) error (SWT.ERROR_NO_HANDLES);
344                         display.hIconCancel = phicon [0];
345                 }
346                 if ((style & SWT.ICON_SEARCH) != 0) {
347                         hwndSearch = OS.CreateWindowEx (0, Label.LabelClass, null,
348                                         OS.WS_CHILD | OS.WS_VISIBLE | OS.WS_CLIPSIBLINGS | OS.SS_OWNERDRAW,
349                                         0, 0, 0, 0, handle, 0, OS.GetModuleHandle (null), null);
350                         if (hwndSearch == 0) error (SWT.ERROR_NO_HANDLES);
351                 }
352                 if ((style & SWT.ICON_CANCEL) != 0) {
353                         state |= TRACK_MOUSE;
354                         hwndCancel = OS.CreateWindowEx (0, Label.LabelClass, null,
355                                         OS.WS_CHILD | OS.WS_CLIPSIBLINGS | OS.SS_OWNERDRAW,
356                                         0, 0, 0, 0, handle, 0, OS.GetModuleHandle (null), null);
357                         if (hwndCancel == 0) error (SWT.ERROR_NO_HANDLES);
358                 }
359         }
360 }
361
362 @Override
363 int applyThemeBackground () {
364         return (backgroundAlpha == 0 || (style & (SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL)) == 0) ? 1 : 0;
365 }
366
367 /**
368  * Adds the listener to the collection of listeners who will
369  * be notified when the receiver's text is modified, by sending
370  * it one of the messages defined in the <code>ModifyListener</code>
371  * interface.
372  *
373  * @param listener the listener which should be notified
374  *
375  * @exception IllegalArgumentException <ul>
376  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
377  * </ul>
378  * @exception SWTException <ul>
379  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
380  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
381  * </ul>
382  *
383  * @see ModifyListener
384  * @see #removeModifyListener
385  */
386 public void addModifyListener (ModifyListener listener) {
387         checkWidget ();
388         if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
389         TypedListener typedListener = new TypedListener (listener);
390         addListener (SWT.Modify, typedListener);
391 }
392
393 /**
394  * Adds a segment listener.
395  * <p>
396  * A <code>SegmentEvent</code> is sent whenever text content is being modified or
397  * a segment listener is added or removed. You can
398  * customize the appearance of text by indicating certain characters to be inserted
399  * at certain text offsets. This may be used for bidi purposes, e.g. when
400  * adjacent segments of right-to-left text should not be reordered relative to
401  * each other.
402  * E.g., multiple Java string literals in a right-to-left language
403  * should generally remain in logical order to each other, that is, the
404  * way they are stored.
405  * </p>
406  * <p>
407  * <b>Warning</b>: This API is currently only implemented on Windows and GTK.
408  * <code>SegmentEvent</code>s won't be sent on Cocoa.
409  * </p>
410  *
411  * @param listener the listener which should be notified
412  *
413  * @exception IllegalArgumentException <ul>
414  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
415  * </ul>
416  * @exception SWTException <ul>
417  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
418  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
419  * </ul>
420  *
421  * @see SegmentEvent
422  * @see SegmentListener
423  * @see #removeSegmentListener
424  *
425  * @since 3.8
426  */
427 public void addSegmentListener (SegmentListener listener) {
428         checkWidget ();
429         if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
430         addListener (SWT.Segments, new TypedListener (listener));
431         clearSegments (true);
432         applySegments ();
433 }
434
435 /**
436  * Adds the listener to the collection of listeners who will
437  * be notified when the control is selected by the user, by sending
438  * it one of the messages defined in the <code>SelectionListener</code>
439  * interface.
440  * <p>
441  * <code>widgetSelected</code> is not called for texts.
442  * <code>widgetDefaultSelected</code> is typically called when ENTER is pressed in a single-line text,
443  * or when ENTER is pressed in a search text. If the receiver has the <code>SWT.SEARCH | SWT.ICON_CANCEL</code> style
444  * and the user cancels the search, the event object detail field contains the value <code>SWT.ICON_CANCEL</code>.
445  * Likewise, if the receiver has the <code>SWT.ICON_SEARCH</code> style and the icon search is selected, the
446  * event object detail field contains the value <code>SWT.ICON_SEARCH</code>.
447  * </p>
448  *
449  * @param listener the listener which should be notified when the control is selected by the user
450  *
451  * @exception IllegalArgumentException <ul>
452  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
453  * </ul>
454  * @exception SWTException <ul>
455  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
456  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
457  * </ul>
458  *
459  * @see SelectionListener
460  * @see #removeSelectionListener
461  * @see SelectionEvent
462  */
463 public void addSelectionListener (SelectionListener listener) {
464         checkWidget ();
465         if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
466         TypedListener typedListener = new TypedListener (listener);
467         addListener (SWT.Selection,typedListener);
468         addListener (SWT.DefaultSelection,typedListener);
469 }
470
471 /**
472  * Adds the listener to the collection of listeners who will
473  * be notified when the receiver's text is verified, by sending
474  * it one of the messages defined in the <code>VerifyListener</code>
475  * interface.
476  *
477  * @param listener the listener which should be notified
478  *
479  * @exception IllegalArgumentException <ul>
480  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
481  * </ul>
482  * @exception SWTException <ul>
483  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
484  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
485  * </ul>
486  *
487  * @see VerifyListener
488  * @see #removeVerifyListener
489  */
490 public void addVerifyListener (VerifyListener listener) {
491         checkWidget ();
492         if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
493         TypedListener typedListener = new TypedListener (listener);
494         addListener (SWT.Verify, typedListener);
495 }
496
497 /**
498  * Appends a string.
499  * <p>
500  * The new text is appended to the text at
501  * the end of the widget.
502  * </p>
503  *
504  * @param string the string to be appended
505  *
506  * @exception IllegalArgumentException <ul>
507  *    <li>ERROR_NULL_ARGUMENT - if the string is null</li>
508  * </ul>
509  * @exception SWTException <ul>
510  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
511  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
512  * </ul>
513  */
514 public void append (String string) {
515         checkWidget ();
516         if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
517         string = Display.withCrLf (string);
518         int length = OS.GetWindowTextLength (handle);
519         if (hooks (SWT.Verify) || filters (SWT.Verify)) {
520                 string = verifyText (string, length, length, null);
521                 if (string == null) return;
522         }
523         OS.SendMessage (handle, OS.EM_SETSEL, length, length);
524         clearSegments (true);
525         TCHAR buffer = new TCHAR (getCodePage (), string, true);
526         /*
527         * Feature in Windows.  When an edit control with ES_MULTILINE
528         * style that does not have the WS_VSCROLL style is full (i.e.
529         * there is no space at the end to draw any more characters),
530         * EM_REPLACESEL sends a WM_CHAR with a backspace character
531         * to remove any further text that is added.  This is an
532         * implementation detail of the edit control that is unexpected
533         * and can cause endless recursion when EM_REPLACESEL is sent
534         * from a WM_CHAR handler.  The fix is to ignore calling the
535         * handler from WM_CHAR.
536         */
537         ignoreCharacter = true;
538         OS.SendMessage (handle, OS.EM_REPLACESEL, 0, buffer);
539         ignoreCharacter = false;
540         OS.SendMessage (handle, OS.EM_SCROLLCARET, 0, 0);
541         if ((state & HAS_AUTO_DIRECTION) != 0) {
542                 super.updateTextDirection (AUTO_TEXT_DIRECTION);
543         }
544         applySegments ();
545 }
546
547 void applySegments () {
548         /*
549          * It is possible (but unlikely), that application code could have
550          * disposed the widget in the modify event. If this happens, return to
551          * cancel the operation.
552          */
553         if (isDisposed() || --clearSegmentsCount != 0) return;
554         if (!hooks (SWT.Segments) && !filters (SWT.Segments)) return;
555         int length = OS.GetWindowTextLength (handle);
556         char [] buffer = new char [length + 1];
557         if (length > 0) OS.GetWindowText (handle, buffer, length + 1);
558         String string = new String (buffer, 0, length);
559         /* Get segments text */
560         Event event = new Event ();
561         event.text = string;
562         event.segments = segments;
563         sendEvent (SWT.Segments, event);
564         segments = event.segments;
565         if (segments == null) return;
566         int nSegments = segments.length;
567         if (nSegments == 0) return;
568         length = string == null ? 0 : string.length ();
569
570         for (int i = 1; i < nSegments; i++) {
571                 if (event.segments [i] < event.segments [i - 1] || event.segments [i] > length) {
572                         error (SWT.ERROR_INVALID_ARGUMENT);
573                 }
574         }
575         char [] segmentsChars = event.segmentsChars;
576         char [] segmentsCharsCrLf = segmentsChars == null ? null : Display.withCrLf(segmentsChars);
577         if (segmentsChars != segmentsCharsCrLf) {
578                 int [] segmentsCrLf = new int [nSegments + Math.min (nSegments, segmentsCharsCrLf.length - segmentsChars.length)];
579                 for (int i = 0, c = 0; i < segmentsChars.length && i < nSegments; i++) {
580                         if (segmentsChars [i] == '\n' && segmentsCharsCrLf [i + c] == '\r') {
581                                 segmentsCrLf [i + c++] = segments [i];
582                         }
583                         segmentsCrLf [i + c] = segments [i];
584                 }
585                 segments = segmentsCrLf;
586                 nSegments = segments.length;
587                 segmentsChars = segmentsCharsCrLf;
588         }
589
590         int limit = (int)OS.SendMessage (handle, OS.EM_GETLIMITTEXT, 0, 0) & 0x7fffffff;
591         OS.SendMessage (handle, OS.EM_SETLIMITTEXT, limit + Math.min (nSegments, LIMIT - limit), 0);
592         length += nSegments;
593         char [] newChars = new char [length + 1];
594         int charCount = 0, segmentCount = 0;
595         char defaultSeparator = getOrientation () == SWT.RIGHT_TO_LEFT ? RTL_MARK : LTR_MARK;
596         while (charCount < length) {
597                 if (segmentCount < nSegments && charCount - segmentCount == segments [segmentCount]) {
598                         char separator = segmentsChars != null && segmentsChars.length > segmentCount ? segmentsChars [segmentCount] : defaultSeparator;
599                         newChars [charCount++] = separator;
600                         segmentCount++;
601                 } else if (string != null) {
602                         newChars [charCount] = string.charAt (charCount++ - segmentCount);
603                 }
604         }
605         while (segmentCount < nSegments) {
606                 segments [segmentCount] = charCount - segmentCount;
607                 char separator = segmentsChars != null && segmentsChars.length > segmentCount ? segmentsChars [segmentCount] : defaultSeparator;
608                 newChars [charCount++] = separator;
609                 segmentCount++;
610         }
611         /* Get the current selection */
612         int [] start = new int [1], end = new int [1];
613         OS.SendMessage (handle, OS.EM_GETSEL, start, end);
614         boolean oldIgnoreCharacter = ignoreCharacter, oldIgnoreModify = ignoreModify, oldIgnoreVerify = ignoreVerify;
615         ignoreCharacter = ignoreModify = ignoreVerify = true;
616         /*
617          * SetWindowText empties the undo buffer and disables undo menu item.
618          * Sending OS.EM_REPLACESEL message instead.
619          */
620         newChars [length] = 0;
621         OS.SendMessage (handle, OS.EM_SETSEL, 0, -1);
622         long undo = OS.SendMessage (handle, OS.EM_CANUNDO, 0, 0);
623         OS.SendMessage (handle, OS.EM_REPLACESEL, undo, newChars);
624         /* Restore selection */
625         start [0] = translateOffset (start [0]);
626         end [0] = translateOffset (end [0]);
627         OS.SendMessage (handle, OS.EM_SETSEL, start [0], end [0]);
628         ignoreCharacter = oldIgnoreCharacter;
629         ignoreModify = oldIgnoreModify;
630         ignoreVerify = oldIgnoreVerify;
631 }
632
633 static int checkStyle (int style) {
634         if ((style & SWT.SINGLE) != 0 && (style & SWT.MULTI) != 0) {
635                 style &= ~SWT.MULTI;
636         }
637         style = checkBits (style, SWT.LEFT, SWT.CENTER, SWT.RIGHT, 0, 0, 0);
638         /*
639          * NOTE: ICON_CANCEL and ICON_SEARCH have the same value as H_SCROLL and
640          * V_SCROLL. The meaning is determined by whether SWT.SEARCH is set.
641          */
642         if ((style & SWT.SEARCH) != 0) {
643                 style |= SWT.SINGLE | SWT.BORDER;
644                 style &= ~(SWT.PASSWORD | SWT.WRAP);
645         } else if ((style & SWT.SINGLE) != 0) {
646                 style &= ~(SWT.H_SCROLL | SWT.V_SCROLL | SWT.WRAP);
647         }
648         if ((style & SWT.WRAP) != 0) {
649                 style |= SWT.MULTI;
650                 style &= ~SWT.H_SCROLL;
651         }
652         if ((style & SWT.MULTI) != 0) style &= ~SWT.PASSWORD;
653         if ((style & (SWT.SINGLE | SWT.MULTI)) != 0) return style;
654         if ((style & (SWT.H_SCROLL | SWT.V_SCROLL)) != 0) return style | SWT.MULTI;
655         return style | SWT.SINGLE;
656 }
657
658 void clearSegments (boolean applyText) {
659         if (clearSegmentsCount++ != 0) return;
660         if (segments == null) return;
661         int nSegments = segments.length;
662         if (nSegments == 0) return;
663         int limit = (int)OS.SendMessage (handle, OS.EM_GETLIMITTEXT, 0, 0) & 0x7fffffff;
664         if (limit < LIMIT) {
665                 OS.SendMessage (handle, OS.EM_SETLIMITTEXT, Math.max (1, limit - nSegments), 0);
666         }
667         if (!applyText) {
668                 segments = null;
669                 return;
670         }
671         boolean oldIgnoreCharacter = ignoreCharacter, oldIgnoreModify = ignoreModify, oldIgnoreVerify = ignoreVerify;
672         ignoreCharacter = ignoreModify = ignoreVerify = true;
673         int length = OS.GetWindowTextLength (handle);
674         int cp = getCodePage ();
675         TCHAR buffer = new TCHAR (cp, length + 1);
676         if (length > 0) OS.GetWindowText (handle, buffer, length + 1);
677         buffer = deprocessText (buffer, 0, -1, true);
678         /* Get the current selection */
679         int [] start = new int [1], end = new int [1];
680         OS.SendMessage (handle, OS.EM_GETSEL, start, end);
681         start [0] = untranslateOffset (start [0]);
682         end [0] = untranslateOffset (end[0]);
683         segments = null;
684         /*
685          * SetWindowText empties the undo buffer and disables undo in the context
686          * menu. Sending OS.EM_REPLACESEL message instead.
687          */
688         OS.SendMessage (handle, OS.EM_SETSEL, 0, -1);
689         long undo = OS.SendMessage (handle, OS.EM_CANUNDO, 0, 0);
690         OS.SendMessage (handle, OS.EM_REPLACESEL, undo, buffer);
691         OS.SendMessage (handle, OS.EM_SETSEL, start [0], end [0]);
692         ignoreCharacter = oldIgnoreCharacter;
693         ignoreModify = oldIgnoreModify;
694         ignoreVerify = oldIgnoreVerify;
695 }
696
697 /**
698  * Clears the selection.
699  *
700  * @exception SWTException <ul>
701  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
702  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
703  * </ul>
704  */
705 public void clearSelection () {
706         checkWidget ();
707         OS.SendMessage (handle, OS.EM_SETSEL, -1, 0);
708 }
709
710 @Override Point computeSizeInPixels (int wHint, int hHint, boolean changed) {
711         checkWidget ();
712         int height = 0, width = 0;
713         if (wHint == SWT.DEFAULT || hHint == SWT.DEFAULT) {
714                 long newFont, oldFont = 0;
715                 long hDC = OS.GetDC (handle);
716                 newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
717                 if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
718                 TEXTMETRIC tm = new TEXTMETRIC ();
719                 OS.GetTextMetrics (hDC, tm);
720                 int count = (style & SWT.SINGLE) != 0 ? 1 : (int)OS.SendMessage (handle, OS.EM_GETLINECOUNT, 0, 0);
721                 height = count * tm.tmHeight;
722                 RECT rect = new RECT ();
723                 int flags = OS.DT_CALCRECT | OS.DT_EDITCONTROL | OS.DT_NOPREFIX;
724                 boolean wrap = (style & SWT.MULTI) != 0 && (style & SWT.WRAP) != 0;
725                 if (wrap && wHint != SWT.DEFAULT) {
726                         flags |= OS.DT_WORDBREAK;
727                         rect.right = wHint;
728                 }
729                 int length = OS.GetWindowTextLength (handle);
730                 if (length != 0) {
731                         char [] buffer = new char [length + 1];
732                         OS.GetWindowText (handle, buffer, length + 1);
733                         OS.DrawText (hDC, buffer, length, rect, flags);
734                         Arrays.fill (buffer, '\0'); // erase sensitive data
735                         width = rect.right - rect.left;
736                 }
737                 if (wrap && hHint == SWT.DEFAULT) {
738                         int newHeight = rect.bottom - rect.top;
739                         if (newHeight != 0) height = newHeight;
740                 }
741                 if ((style & SWT.SINGLE) != 0 && message.length () > 0) {
742                         OS.SetRect (rect, 0, 0, 0, 0);
743                         char [] buffer = message.toCharArray ();
744                         OS.DrawText (hDC, buffer, buffer.length, rect, flags);
745                         width = Math.max (width, rect.right - rect.left);
746                 }
747                 if (newFont != 0) OS.SelectObject (hDC, oldFont);
748                 OS.ReleaseDC (handle, hDC);
749         }
750         if (width == 0) width = DEFAULT_WIDTH;
751         if (height == 0) height = DEFAULT_HEIGHT;
752         if (wHint != SWT.DEFAULT) width = wHint;
753         if (hHint != SWT.DEFAULT) height = hHint;
754         Rectangle trim = computeTrimInPixels (0, 0, width, height);
755         return new Point (trim.width, trim.height);
756 }
757
758 @Override Rectangle computeTrimInPixels (int x, int y, int width, int height) {
759         checkWidget ();
760         Rectangle rect = super.computeTrimInPixels (x, y, width, height);
761         /*
762         * The preferred height of a single-line text widget
763         * has been hand-crafted to be the same height as
764         * the single-line text widget in an editable combo
765         * box.
766         */
767         long margins = OS.SendMessage(handle, OS.EM_GETMARGINS, 0, 0);
768         rect.x -= OS.LOWORD (margins);
769         rect.width += OS.LOWORD (margins) + OS.HIWORD (margins);
770         if ((style & SWT.H_SCROLL) != 0) rect.width++;
771         if ((style & SWT.BORDER) != 0) {
772                 rect.x -= 1;
773                 rect.y -= 1;
774                 rect.width += 2;
775                 rect.height += 2;
776         }
777         return rect;
778 }
779
780 /**
781  * Copies the selected text.
782  * <p>
783  * The current selection is copied to the clipboard.
784  * </p>
785  *
786  * @exception SWTException <ul>
787  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
788  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
789  * </ul>
790  */
791 public void copy () {
792         checkWidget ();
793         OS.SendMessage (handle, OS.WM_COPY, 0, 0);
794 }
795
796 @Override
797 void createWidget () {
798         super.createWidget ();
799         message = "";
800         doubleClick = true;
801         setTabStops (tabs = 8);
802         fixAlignment ();
803 }
804
805 /**
806  * Cuts the selected text.
807  * <p>
808  * The current selection is first copied to the
809  * clipboard and then deleted from the widget.
810  * </p>
811  *
812  * @exception SWTException <ul>
813  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
814  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
815  * </ul>
816  */
817 public void cut () {
818         checkWidget ();
819         if ((style & SWT.READ_ONLY) != 0) return;
820         OS.SendMessage (handle, OS.WM_CUT, 0, 0);
821 }
822
823 @Override
824 int defaultBackground () {
825         int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
826         if ((bits & OS.ES_READONLY) != 0 || !OS.IsWindowEnabled (handle)) {
827                 return OS.GetSysColor (OS.COLOR_3DFACE);
828         }
829         return OS.GetSysColor (OS.COLOR_WINDOW);
830 }
831
832 TCHAR deprocessText (TCHAR text, int start, int end, boolean terminate) {
833         if (text == null) return null;
834         int length = text.length ();
835         char [] chars;
836         if (start < 0) start = 0;
837         chars = text.chars;
838         if (text.chars [length - 1] == 0) length--;
839         if (end == -1) end = length;
840         if (segments != null && end > segments [0]) {
841                 int nSegments = segments.length;
842                 if (nSegments > 0 && start <= segments [nSegments - 1]) {
843                         int nLeadSegments = 0;
844                         while (start - nLeadSegments > segments [nLeadSegments]) nLeadSegments++;
845                         int segmentCount = nLeadSegments;
846                         for (int i = start; i < end; i++) {
847                                 if (segmentCount < nSegments && i - segmentCount == segments [segmentCount]) {
848                                         ++segmentCount;
849                                 } else {
850                                         chars [i - segmentCount + nLeadSegments] = chars [i];
851                                 }
852                         }
853                         length = end - start - segmentCount + nLeadSegments;
854                 }
855         }
856         if (start != 0 || end != length) {
857                 char [] newChars = new char [length];
858                 System.arraycopy(chars, start, newChars, 0, length);
859                 return new TCHAR (getCodePage (), newChars, terminate);
860         }
861         return text;
862 }
863
864 @Override
865 boolean dragDetect (long hwnd, int x, int y, boolean filter, boolean [] detect, boolean [] consume) {
866         if (filter) {
867                 int [] start = new int [1], end = new int [1];
868                 OS.SendMessage (handle, OS.EM_GETSEL, start, end);
869                 if (start [0] != end [0]) {
870                         long lParam = OS.MAKELPARAM (x, y);
871                         int position = OS.LOWORD (OS.SendMessage (handle, OS.EM_CHARFROMPOS, 0, lParam));
872                         if (start [0] <= position && position < end [0]) {
873                                 if (super.dragDetect (hwnd, x, y, filter, detect, consume)) {
874                                         if (consume != null) consume [0] = true;
875                                         return true;
876                                 }
877                         }
878                 }
879                 return false;
880         }
881         return super.dragDetect (hwnd, x, y, filter, detect, consume);
882 }
883
884 void fixAlignment () {
885         /*
886         * Feature in Windows.  When the edit control is not
887         * mirrored, it uses WS_EX_RIGHT, WS_EX_RTLREADING and
888         * WS_EX_LEFTSCROLLBAR to give the control a right to
889         * left appearance.  This causes the control to be lead
890         * aligned no matter what alignment was specified by
891         * the programmer.  For example, setting ES_RIGHT and
892         * WS_EX_LAYOUTRTL should cause the contents of the
893         * control to be left (trail) aligned in a mirrored world.
894         * When the orientation is changed by the user or
895         * specified by the programmer, WS_EX_RIGHT conflicts
896         * with the mirrored alignment.  The fix is to clear
897         * or set WS_EX_RIGHT to achieve the correct alignment
898         * according to the orientation and mirroring.
899         */
900         if ((style & SWT.MIRRORED) != 0) return;
901         int bits1 = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
902         int bits2 = OS.GetWindowLong (handle, OS.GWL_STYLE);
903         if ((style & SWT.LEFT_TO_RIGHT) != 0) {
904                 if ((style & SWT.RIGHT) != 0) {
905                         bits1 |= OS.WS_EX_RIGHT;
906                         bits2 |= OS.ES_RIGHT;
907                 }
908                 if ((style & SWT.LEFT) != 0) {
909                         bits1 &= ~OS.WS_EX_RIGHT;
910                         bits2 &= ~OS.ES_RIGHT;
911                 }
912         } else {
913                 if ((style & SWT.RIGHT) != 0) {
914                         bits1 &= ~OS.WS_EX_RIGHT;
915                         bits2 &= ~OS.ES_RIGHT;
916                 }
917                 if ((style & SWT.LEFT) != 0) {
918                         bits1 |= OS.WS_EX_RIGHT;
919                         bits2 |= OS.ES_RIGHT;
920                 }
921         }
922         if ((style & SWT.CENTER) != 0) {
923                 bits2 |= OS.ES_CENTER;
924         }
925         OS.SetWindowLong (handle, OS.GWL_EXSTYLE, bits1);
926         OS.SetWindowLong (handle, OS.GWL_STYLE, bits2);
927 }
928
929 @Override int getBorderWidthInPixels () {
930         checkWidget ();
931         /*
932         * Feature in Windows 2000 and XP.  Despite the fact that WS_BORDER
933         * is set when the edit control is created, the style bit is cleared.
934         * The fix is to avoid the check for WS_BORDER and use the SWT widget
935         * style bits instead.
936         */
937 //      if ((style & SWT.BORDER) != 0 && (style & SWT.FLAT) != 0) {
938 //              return OS.GetSystemMetrics (OS.SM_CXBORDER);
939 //      }
940         return super.getBorderWidthInPixels ();
941 }
942
943 /**
944  * Returns the line number of the caret.
945  * <p>
946  * The line number of the caret is returned.
947  * </p>
948  *
949  * @return the line number
950  *
951  * @exception SWTException <ul>
952  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
953  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
954  * </ul>
955  */
956 public int getCaretLineNumber () {
957         checkWidget ();
958         return (int)OS.SendMessage (handle, OS.EM_LINEFROMCHAR, -1, 0);
959 }
960
961 /**
962  * Returns a point describing the location of the caret relative
963  * to the receiver.
964  *
965  * @return a point, the location of the caret
966  *
967  * @exception SWTException <ul>
968  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
969  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
970  * </ul>
971  */
972 public Point getCaretLocation () {
973         checkWidget ();
974         return DPIUtil.autoScaleDown(getCaretLocationInPixels());
975 }
976
977 Point getCaretLocationInPixels () {
978         /*
979         * Bug in Windows.  For some reason, Windows is unable
980         * to return the pixel coordinates of the last character
981         * in the widget.  The fix is to temporarily insert a
982         * space, query the coordinates and delete the space.
983         * The selection is always an i-beam in this case because
984         * this is the only time the start of the selection can
985         * be equal to the last character position in the widget.
986         * If EM_POSFROMCHAR fails for any other reason, return
987         * pixel coordinates (0,0).
988         */
989         int position = translateOffset (getCaretPosition ());
990         long caretPos = OS.SendMessage (handle, OS.EM_POSFROMCHAR, position, 0);
991         if (caretPos == -1) {
992                 caretPos = 0;
993                 if (position >= OS.GetWindowTextLength (handle)) {
994                         int [] start = new int [1], end = new int [1];
995                         OS.SendMessage (handle, OS.EM_GETSEL, start, end);
996                         OS.SendMessage (handle, OS.EM_SETSEL, position, position);
997                         /*
998                         * Feature in Windows.  When an edit control with ES_MULTILINE
999                         * style that does not have the WS_VSCROLL style is full (i.e.
1000                         * there is no space at the end to draw any more characters),
1001                         * EM_REPLACESEL sends a WM_CHAR with a backspace character
1002                         * to remove any further text that is added.  This is an
1003                         * implementation detail of the edit control that is unexpected
1004                         * and can cause endless recursion when EM_REPLACESEL is sent
1005                         * from a WM_CHAR handler.  The fix is to ignore calling the
1006                         * handler from WM_CHAR.
1007                         */
1008                         ignoreCharacter = ignoreModify = true;
1009                         OS.SendMessage (handle, OS.EM_REPLACESEL, 0, new char [] {' ', '\0'});
1010                         caretPos = OS.SendMessage (handle, OS.EM_POSFROMCHAR, position, 0);
1011                         OS.SendMessage (handle, OS.EM_SETSEL, position, position + 1);
1012                         OS.SendMessage (handle, OS.EM_REPLACESEL, 0, new char [] {'\0'});
1013                         ignoreCharacter = ignoreModify = false;
1014                         OS.SendMessage (handle, OS.EM_SETSEL, start [0], start [0]);
1015                         OS.SendMessage (handle, OS.EM_SETSEL, start [0], end [0]);
1016                 }
1017         }
1018         return new Point (OS.GET_X_LPARAM (caretPos), OS.GET_Y_LPARAM (caretPos));
1019 }
1020
1021 /**
1022  * Returns the character position of the caret.
1023  * <p>
1024  * Indexing is zero based.
1025  * </p>
1026  *
1027  * @return the position of the caret
1028  *
1029  * @exception SWTException <ul>
1030  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1031  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1032  * </ul>
1033  */
1034 public int getCaretPosition () {
1035         checkWidget ();
1036         int [] start = new int [1], end = new int [1];
1037         OS.SendMessage (handle, OS.EM_GETSEL, start, end);
1038         /*
1039         * In Windows, there is no API to get the position of the caret
1040         * when the selection is not an i-beam.  The best that can be done
1041         * is to query the pixel position of the current caret and compare
1042         * it to the pixel position of the start and end of the selection.
1043         *
1044         * NOTE:  This does not work when the i-beam belongs to another
1045         * control.  In this case, guess that the i-beam is at the start
1046         * of the selection.
1047         */
1048         int caret = start [0];
1049         if (start [0] != end [0]) {
1050                 int startLine = (int)OS.SendMessage (handle, OS.EM_LINEFROMCHAR, start [0], 0);
1051                 int endLine = (int)OS.SendMessage (handle, OS.EM_LINEFROMCHAR, end [0], 0);
1052                 if (startLine == endLine) {
1053                         int idThread = OS.GetWindowThreadProcessId (handle, null);
1054                         GUITHREADINFO lpgui = new GUITHREADINFO ();
1055                         lpgui.cbSize = GUITHREADINFO.sizeof;
1056                         if (OS.GetGUIThreadInfo (idThread, lpgui)) {
1057                                 if (lpgui.hwndCaret == handle || lpgui.hwndCaret == 0) {
1058                                         POINT ptCurrentPos = new POINT ();
1059                                         if (OS.GetCaretPos (ptCurrentPos)) {
1060                                                 long endPos = OS.SendMessage (handle, OS.EM_POSFROMCHAR, end [0], 0);
1061                                                 if (endPos == -1) {
1062                                                         long startPos = OS.SendMessage (handle, OS.EM_POSFROMCHAR, start [0], 0);
1063                                                         int startX = OS.GET_X_LPARAM (startPos);
1064                                                         if (ptCurrentPos.x > startX) caret = end [0];
1065                                                 } else {
1066                                                         int endX = OS.GET_X_LPARAM (endPos);
1067                                                         if (ptCurrentPos.x >= endX) caret = end [0];
1068                                                 }
1069                                         }
1070                                 }
1071                         }
1072                 } else {
1073                         int caretPos = (int)OS.SendMessage (handle, OS.EM_LINEINDEX, -1, 0);
1074                         int caretLine = (int)OS.SendMessage (handle, OS.EM_LINEFROMCHAR, caretPos, 0);
1075                         if (caretLine == endLine) caret = end [0];
1076                 }
1077         }
1078         return untranslateOffset (caret);
1079 }
1080
1081 /**
1082  * Returns the number of characters.
1083  *
1084  * @return number of characters in the widget
1085  *
1086  * @exception SWTException <ul>
1087  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1088  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1089  * </ul>
1090  */
1091 public int getCharCount () {
1092         checkWidget ();
1093         int length = OS.GetWindowTextLength (handle);
1094         return untranslateOffset (length);
1095 }
1096
1097 /**
1098  * Returns the double click enabled flag.
1099  * <p>
1100  * The double click flag enables or disables the
1101  * default action of the text widget when the user
1102  * double clicks.
1103  * </p>
1104  *
1105  * @return whether or not double click is enabled
1106  *
1107  * @exception SWTException <ul>
1108  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1109  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1110  * </ul>
1111  */
1112 public boolean getDoubleClickEnabled () {
1113         checkWidget ();
1114         return doubleClick;
1115 }
1116
1117 /**
1118  * Returns the echo character.
1119  * <p>
1120  * The echo character is the character that is
1121  * displayed when the user enters text or the
1122  * text is changed by the programmer.
1123  * </p>
1124  *
1125  * @return the echo character
1126  *
1127  * @exception SWTException <ul>
1128  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1129  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1130  * </ul>
1131  *
1132  * @see #setEchoChar
1133  */
1134 public char getEchoChar () {
1135         checkWidget ();
1136         return (char) OS.SendMessage (handle, OS.EM_GETPASSWORDCHAR, 0, 0);
1137 }
1138
1139 /**
1140  * Returns the editable state.
1141  *
1142  * @return whether or not the receiver is editable
1143  *
1144  * @exception SWTException <ul>
1145  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1146  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1147  * </ul>
1148  */
1149 public boolean getEditable () {
1150         checkWidget ();
1151         int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
1152         return (bits & OS.ES_READONLY) == 0;
1153 }
1154
1155 /**
1156  * Returns the number of lines.
1157  *
1158  * @return the number of lines in the widget
1159  *
1160  * @exception SWTException <ul>
1161  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1162  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1163  * </ul>
1164  */
1165 public int getLineCount () {
1166         checkWidget ();
1167         return (int)OS.SendMessage (handle, OS.EM_GETLINECOUNT, 0, 0);
1168 }
1169
1170 /**
1171  * Returns the line delimiter.
1172  *
1173  * @return a string that is the line delimiter
1174  *
1175  * @exception SWTException <ul>
1176  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1177  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1178  * </ul>
1179  *
1180  * @see #DELIMITER
1181  */
1182 public String getLineDelimiter () {
1183         checkWidget ();
1184         return DELIMITER;
1185 }
1186
1187 /**
1188  * Returns the height of a line.
1189  *
1190  * @return the height of a row of text
1191  *
1192  * @exception SWTException <ul>
1193  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1194  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1195  * </ul>
1196  */
1197 public int getLineHeight () {
1198         checkWidget ();
1199         return DPIUtil.autoScaleDown(getLineHeightInPixels ());
1200 }
1201
1202 int getLineHeightInPixels () {
1203         long newFont, oldFont = 0;
1204         long hDC = OS.GetDC (handle);
1205         newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
1206         if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
1207         TEXTMETRIC tm = new TEXTMETRIC ();
1208         OS.GetTextMetrics (hDC, tm);
1209         if (newFont != 0) OS.SelectObject (hDC, oldFont);
1210         OS.ReleaseDC (handle, hDC);
1211         return tm.tmHeight;
1212 }
1213
1214 /**
1215  * Returns the orientation of the receiver, which will be one of the
1216  * constants <code>SWT.LEFT_TO_RIGHT</code> or <code>SWT.RIGHT_TO_LEFT</code>.
1217  *
1218  * @return the orientation style
1219  *
1220  * @exception SWTException <ul>
1221  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1222  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1223  * </ul>
1224  *
1225  * @since 2.1.2
1226  */
1227 @Override
1228 public int getOrientation () {
1229         return super.getOrientation ();
1230 }
1231
1232 /**
1233  * Returns the widget message.  The message text is displayed
1234  * as a hint for the user, indicating the purpose of the field.
1235  * <p>
1236  * Typically this is used in conjunction with <code>SWT.SEARCH</code>.
1237  * </p>
1238  *
1239  * @return the widget message
1240  *
1241  * @exception SWTException <ul>
1242  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1243  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1244  * </ul>
1245  *
1246  * @since 3.3
1247  */
1248 public String getMessage () {
1249         checkWidget ();
1250         return message;
1251 }
1252
1253 /**
1254  * Returns the character position at the given point in the receiver
1255  * or -1 if no such position exists. The point is in the coordinate
1256  * system of the receiver.
1257  * <p>
1258  * Indexing is zero based.
1259  * </p>
1260  *
1261  * @return the position of the caret
1262  *
1263  * @exception SWTException <ul>
1264  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1265  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1266  * </ul>
1267  *
1268  * @since 3.3
1269  */
1270 //TODO - Javadoc
1271 /*public*/ int getPosition (Point point) {
1272         checkWidget();
1273         if (point == null) error (SWT.ERROR_NULL_ARGUMENT);
1274         long lParam = OS.MAKELPARAM (point.x, point.y);
1275         int position = OS.LOWORD (OS.SendMessage (handle, OS.EM_CHARFROMPOS, 0, lParam));
1276         return untranslateOffset (position);
1277 }
1278
1279 /**
1280  * Returns a <code>Point</code> whose x coordinate is the
1281  * character position representing the start of the selected
1282  * text, and whose y coordinate is the character position
1283  * representing the end of the selection. An "empty" selection
1284  * is indicated by the x and y coordinates having the same value.
1285  * <p>
1286  * Indexing is zero based.  The range of a selection is from
1287  * 0..N where N is the number of characters in the widget.
1288  * </p>
1289  *
1290  * @return a point representing the selection start and end
1291  *
1292  * @exception SWTException <ul>
1293  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1294  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1295  * </ul>
1296  */
1297 public Point getSelection () {
1298         checkWidget ();
1299         int [] start = new int [1], end = new int [1];
1300         OS.SendMessage (handle, OS.EM_GETSEL, start, end);
1301         return new Point (untranslateOffset (start [0]), untranslateOffset (end [0]));
1302 }
1303
1304 /**
1305  * Returns the number of selected characters.
1306  *
1307  * @return the number of selected characters.
1308  *
1309  * @exception SWTException <ul>
1310  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1311  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1312  * </ul>
1313  */
1314 public int getSelectionCount () {
1315         checkWidget ();
1316         Point selection = getSelection ();
1317         return selection.y - selection.x;
1318 }
1319
1320 /**
1321  * Gets the selected text, or an empty string if there is no current selection.
1322  *
1323  * @return the selected text
1324  *
1325  * @exception SWTException <ul>
1326  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1327  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1328  * </ul>
1329  */
1330 public String getSelectionText () {
1331         checkWidget ();
1332         int length = OS.GetWindowTextLength (handle);
1333         if (length == 0) return "";
1334         int [] start = new int [1], end = new int [1];
1335         OS.SendMessage (handle, OS.EM_GETSEL, start, end);
1336         if (start [0] == end [0]) return "";
1337         TCHAR buffer = new TCHAR (getCodePage (), length + 1);
1338         OS.GetWindowText (handle, buffer, length + 1);
1339         if (segments != null) {
1340                 buffer = deprocessText (buffer, start [0], end [0], false);
1341                 return buffer.toString ();
1342         }
1343         return buffer.toString (start [0], end [0] - start [0]);
1344 }
1345
1346 /**
1347  * Returns the number of tabs.
1348  * <p>
1349  * Tab stop spacing is specified in terms of the
1350  * space (' ') character.  The width of a single
1351  * tab stop is the pixel width of the spaces.
1352  * </p>
1353  *
1354  * @return the number of tab characters
1355  *
1356  * @exception SWTException <ul>
1357  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1358  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1359  * </ul>
1360  */
1361 public int getTabs () {
1362         checkWidget ();
1363         return tabs;
1364 }
1365
1366 int getTabWidth (int tabs) {
1367         long oldFont = 0;
1368         RECT rect = new RECT ();
1369         long hDC = OS.GetDC (handle);
1370         long newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
1371         if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
1372         int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE | OS.DT_NOPREFIX;
1373         OS.DrawText (hDC, new char [] {' '}, 1, rect, flags);
1374         if (newFont != 0) OS.SelectObject (hDC, oldFont);
1375         OS.ReleaseDC (handle, hDC);
1376         return (rect.right - rect.left) * tabs;
1377 }
1378
1379 /**
1380  * Returns the widget text.
1381  * <p>
1382  * The text for a text widget is the characters in the widget, or
1383  * an empty string if this has never been set.
1384  * </p>
1385  *
1386  * @return the widget text
1387  *
1388  * @exception SWTException <ul>
1389  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1390  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1391  * </ul>
1392  */
1393 public String getText () {
1394         checkWidget ();
1395         int length = OS.GetWindowTextLength (handle);
1396         if (length == 0) return "";
1397         TCHAR buffer = new TCHAR (getCodePage (), length + 1);
1398         OS.GetWindowText (handle, buffer, length + 1);
1399         if (segments != null) {
1400                 buffer = deprocessText (buffer, 0, -1, false);
1401                 return buffer.toString ();
1402         }
1403         return buffer.toString (0, length);
1404 }
1405
1406 /**
1407  * Returns the widget's text as a character array.
1408  * <p>
1409  * The text for a text widget is the characters in the widget, or
1410  * a zero-length array if this has never been set.
1411  * </p>
1412  * <p>
1413  * Note: Use this API to prevent the text from being written into a String
1414  * object whose lifecycle is outside of your control. This can help protect
1415  * the text, for example, when the widget is used as a password field.
1416  * However, the text can't be protected if an {@link SWT#Segments} or
1417  * {@link SWT#Verify} listener has been added to the widget.
1418  * </p>
1419  *
1420  * @return a character array that contains the widget's text
1421  *
1422  * @exception SWTException <ul>
1423  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1424  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1425  * </ul>
1426  *
1427  * @see #setTextChars(char[])
1428  *
1429  * @since 3.7
1430  */
1431 public char[] getTextChars () {
1432         checkWidget ();
1433         int length = OS.GetWindowTextLength (handle);
1434         if (length == 0) return new char[0];
1435         TCHAR buffer = new TCHAR (getCodePage (), length + 1);
1436         OS.GetWindowText (handle, buffer, length + 1);
1437         if (segments != null) buffer = deprocessText (buffer, 0, -1, false);
1438         char [] chars = new char [length];
1439         System.arraycopy (buffer.chars, 0, chars, 0, length);
1440         buffer.clear ();
1441         return chars;
1442 }
1443
1444 /**
1445  * Returns a range of text.  Returns an empty string if the
1446  * start of the range is greater than the end.
1447  * <p>
1448  * Indexing is zero based.  The range of
1449  * a selection is from 0..N-1 where N is
1450  * the number of characters in the widget.
1451  * </p>
1452  *
1453  * @param start the start of the range
1454  * @param end the end of the range
1455  * @return the range of text
1456  *
1457  * @exception SWTException <ul>
1458  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1459  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1460  * </ul>
1461  */
1462 public String getText (int start, int end) {
1463         checkWidget ();
1464         if (!(start <= end && 0 <= end)) return "";
1465         int length = OS.GetWindowTextLength (handle);
1466         end = Math.min (end, untranslateOffset (length) - 1);
1467         if (start > end) return "";
1468         start = Math.max (0, start);
1469         /*
1470         * NOTE: The current implementation uses substring ()
1471         * which can reference a potentially large character
1472         * array.
1473         */
1474         return getText ().substring (start, end + 1);
1475 }
1476
1477 /**
1478  * Returns the maximum number of characters that the receiver is capable of holding.
1479  * <p>
1480  * If this has not been changed by <code>setTextLimit()</code>,
1481  * it will be the constant <code>Text.LIMIT</code>.
1482  * </p>
1483  *
1484  * @return the text limit
1485  *
1486  * @exception SWTException <ul>
1487  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1488  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1489  * </ul>
1490  *
1491  * @see #LIMIT
1492  */
1493 public int getTextLimit () {
1494         checkWidget ();
1495         int limit = (int)OS.SendMessage (handle, OS.EM_GETLIMITTEXT, 0, 0) & 0x7FFFFFFF;
1496         if (segments != null && limit < LIMIT) limit = Math.max (1, limit - segments.length);
1497         return limit;
1498 }
1499
1500 /**
1501  * Returns the zero-relative index of the line which is currently
1502  * at the top of the receiver.
1503  * <p>
1504  * This index can change when lines are scrolled or new lines are added or removed.
1505  * </p>
1506  *
1507  * @return the index of the top line
1508  *
1509  * @exception SWTException <ul>
1510  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1511  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1512  * </ul>
1513  */
1514 public int getTopIndex () {
1515         checkWidget ();
1516         if ((style & SWT.SINGLE) != 0) return 0;
1517         return (int)OS.SendMessage (handle, OS.EM_GETFIRSTVISIBLELINE, 0, 0);
1518 }
1519
1520 /**
1521  * Returns the top SWT logical point.
1522  * <p>
1523  * The top point is the SWT logical point position of the line
1524  * that is currently at the top of the widget.  On
1525  * some platforms, a text widget can be scrolled by
1526  * points instead of lines so that a partial line
1527  * is displayed at the top of the widget.
1528  * </p><p>
1529  * The top SWT logical point changes when the widget is scrolled.
1530  * The top SWT logical point does not include the widget trimming.
1531  * </p>
1532  *
1533  * @return the SWT logical point position of the top line
1534  *
1535  * @exception SWTException <ul>
1536  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1537  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1538  * </ul>
1539  */
1540 public int getTopPixel () {
1541         checkWidget ();
1542         return DPIUtil.autoScaleDown(getTopPixelInPixels());
1543 }
1544
1545 int getTopPixelInPixels () {
1546         /*
1547         * Note, EM_GETSCROLLPOS is implemented in Rich Edit 3.0
1548         * and greater.  The plain text widget and previous versions
1549         * of Rich Edit return zero.
1550         */
1551         int [] buffer = new int [2];
1552         long code = OS.SendMessage (handle, OS.EM_GETSCROLLPOS, 0, buffer);
1553         if (code == 1) return buffer [1];
1554         return getTopIndex () * getLineHeightInPixels ();
1555 }
1556
1557 /**
1558  * Inserts a string.
1559  * <p>
1560  * The old selection is replaced with the new text.
1561  * </p>
1562  *
1563  * @param string the string
1564  *
1565  * @exception IllegalArgumentException <ul>
1566  *    <li>ERROR_NULL_ARGUMENT - if the string is <code>null</code></li>
1567  * </ul>
1568  * @exception SWTException <ul>
1569  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1570  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1571  * </ul>
1572  */
1573 public void insert (String string) {
1574         checkWidget ();
1575         if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
1576         string = Display.withCrLf (string);
1577         if (hooks (SWT.Verify) || filters (SWT.Verify)) {
1578                 int [] start = new int [1], end = new int [1];
1579                 OS.SendMessage (handle, OS.EM_GETSEL, start, end);
1580                 string = verifyText (string, start [0], end [0], null);
1581                 if (string == null) return;
1582         }
1583         clearSegments (true);
1584         TCHAR buffer = new TCHAR (getCodePage (), string, true);
1585         /*
1586         * Feature in Windows.  When an edit control with ES_MULTILINE
1587         * style that does not have the WS_VSCROLL style is full (i.e.
1588         * there is no space at the end to draw any more characters),
1589         * EM_REPLACESEL sends a WM_CHAR with a backspace character
1590         * to remove any further text that is added.  This is an
1591         * implementation detail of the edit control that is unexpected
1592         * and can cause endless recursion when EM_REPLACESEL is sent
1593         * from a WM_CHAR handler.  The fix is to ignore calling the
1594         * handler from WM_CHAR.
1595         */
1596         ignoreCharacter = true;
1597         OS.SendMessage (handle, OS.EM_REPLACESEL, 0, buffer);
1598         ignoreCharacter = false;
1599         if ((state & HAS_AUTO_DIRECTION) != 0) {
1600                 super.updateTextDirection (AUTO_TEXT_DIRECTION);
1601         }
1602         applySegments ();
1603 }
1604
1605 /**
1606  * Pastes text from clipboard.
1607  * <p>
1608  * The selected text is deleted from the widget
1609  * and new text inserted from the clipboard.
1610  * </p>
1611  *
1612  * @exception SWTException <ul>
1613  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1614  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1615  * </ul>
1616  */
1617 public void paste () {
1618         checkWidget ();
1619         if ((style & SWT.READ_ONLY) != 0) return;
1620         OS.SendMessage (handle, OS.WM_PASTE, 0, 0);
1621 }
1622
1623 @Override
1624 void releaseWidget () {
1625         super.releaseWidget ();
1626         message = null;
1627 }
1628
1629 /**
1630  * Removes the listener from the collection of listeners who will
1631  * be notified when the receiver's text is modified.
1632  *
1633  * @param listener the listener which should no longer be notified
1634  *
1635  * @exception IllegalArgumentException <ul>
1636  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1637  * </ul>
1638  * @exception SWTException <ul>
1639  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1640  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1641  * </ul>
1642  *
1643  * @see ModifyListener
1644  * @see #addModifyListener
1645  */
1646 public void removeModifyListener (ModifyListener listener) {
1647         checkWidget ();
1648         if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
1649         if (eventTable == null) return;
1650         eventTable.unhook (SWT.Modify, listener);
1651 }
1652
1653 /**
1654  * Removes the listener from the collection of listeners who will
1655  * be notified when the receiver's text is modified.
1656  *
1657  * @param listener the listener which should no longer be notified
1658  *
1659  * @exception IllegalArgumentException <ul>
1660  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1661  * </ul>
1662  * @exception SWTException <ul>
1663  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1664  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1665  * </ul>
1666  *
1667  * @see SegmentEvent
1668  * @see SegmentListener
1669  * @see #addSegmentListener
1670  *
1671  * @since 3.8
1672  */
1673 public void removeSegmentListener (SegmentListener listener) {
1674         checkWidget ();
1675         if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
1676         eventTable.unhook (SWT.Segments, listener);
1677         clearSegments (true);
1678         applySegments ();
1679 }
1680
1681 /**
1682  * Removes the listener from the collection of listeners who will
1683  * be notified when the control is selected by the user.
1684  *
1685  * @param listener the listener which should no longer be notified
1686  *
1687  * @exception IllegalArgumentException <ul>
1688  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1689  * </ul>
1690  * @exception SWTException <ul>
1691  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1692  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1693  * </ul>
1694  *
1695  * @see SelectionListener
1696  * @see #addSelectionListener
1697  */
1698 public void removeSelectionListener (SelectionListener listener) {
1699         checkWidget ();
1700         if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
1701         if (eventTable == null) return;
1702         eventTable.unhook (SWT.Selection, listener);
1703         eventTable.unhook (SWT.DefaultSelection,listener);
1704 }
1705
1706 /**
1707  * Removes the listener from the collection of listeners who will
1708  * be notified when the control is verified.
1709  *
1710  * @param listener the listener which should no longer be notified
1711  *
1712  * @exception IllegalArgumentException <ul>
1713  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
1714  * </ul>
1715  * @exception SWTException <ul>
1716  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1717  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1718  * </ul>
1719  *
1720  * @see VerifyListener
1721  * @see #addVerifyListener
1722  */
1723 public void removeVerifyListener (VerifyListener listener) {
1724         checkWidget ();
1725         if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
1726         if (eventTable == null) return;
1727         eventTable.unhook (SWT.Verify, listener);
1728 }
1729
1730 @Override
1731 int resolveTextDirection() {
1732         int textDirection = SWT.NONE;
1733         int length = OS.GetWindowTextLength (handle);
1734         if (length > 0) {
1735                 TCHAR buffer = new TCHAR (getCodePage (), length + 1);
1736                 OS.GetWindowText (handle, buffer, length + 1);
1737                 if (segments != null) {
1738                         buffer = deprocessText (buffer, 0, -1, false);
1739                         textDirection = BidiUtil.resolveTextDirection(buffer.toString ());
1740                 } else {
1741                         textDirection = BidiUtil.resolveTextDirection(buffer.toString (0, length));
1742                 }
1743                 if (textDirection == SWT.NONE) {
1744                         /*
1745                          * Force direction update also when there are no strong bidi chars.
1746                         */
1747                         textDirection = (style & SWT.RIGHT_TO_LEFT) != 0 ? SWT.RIGHT_TO_LEFT : SWT.LEFT_TO_RIGHT;
1748                 }
1749         }
1750         return textDirection;
1751 }
1752
1753 /**
1754  * Selects all the text in the receiver.
1755  *
1756  * @exception SWTException <ul>
1757  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1758  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1759  * </ul>
1760  */
1761 public void selectAll () {
1762         checkWidget ();
1763         OS.SendMessage (handle, OS.EM_SETSEL, 0, -1);
1764 }
1765
1766 @Override
1767 boolean sendKeyEvent (int type, int msg, long wParam, long lParam, Event event) {
1768         if (!super.sendKeyEvent (type, msg, wParam, lParam, event)) {
1769                 return false;
1770         }
1771         if ((style & SWT.READ_ONLY) != 0) return true;
1772         if (ignoreVerify) return true;
1773         if (type != SWT.KeyDown) return true;
1774         if (msg != OS.WM_CHAR && msg != OS.WM_KEYDOWN && msg != OS.WM_IME_CHAR) {
1775                 return true;
1776         }
1777         if (event.character == 0) return true;
1778         if (!hooks (SWT.Verify) && !filters (SWT.Verify)) return true;
1779         char key = event.character;
1780         int stateMask = event.stateMask;
1781
1782         /*
1783         * Disable all magic keys that could modify the text
1784         * and don't send events when Alt, Shift or Ctrl is
1785         * pressed.
1786         */
1787         switch (msg) {
1788                 case OS.WM_CHAR:
1789                         if (key != 0x08 && key != 0x7F && key != '\r' && key != '\t' && key != '\n') break;
1790                         // FALL THROUGH
1791                 case OS.WM_KEYDOWN:
1792                         if ((stateMask & (SWT.ALT | SWT.SHIFT | SWT.CONTROL)) != 0) return false;
1793                         break;
1794         }
1795
1796         /*
1797         * Feature in Windows.  If the left button is down in
1798         * the text widget, it refuses the character.  The fix
1799         * is to detect this case and avoid sending a verify
1800         * event.
1801         */
1802         if (OS.GetKeyState (OS.VK_LBUTTON) < 0) {
1803                 if (handle == OS.GetCapture()) return true;
1804         }
1805
1806         /* Verify the character */
1807         String oldText = "";
1808         int [] start = new int [1], end = new int [1];
1809         OS.SendMessage (handle, OS.EM_GETSEL, start, end);
1810         switch (key) {
1811                 case 0x08:      /* Bs */
1812                         if (start [0] == end [0]) {
1813                                 if (start [0] == 0) return true;
1814                                 int lineStart = (int)OS.SendMessage (handle, OS.EM_LINEINDEX, -1, 0);
1815                                 if (start [0] == lineStart) {
1816                                         start [0] = start [0] - DELIMITER.length ();
1817                                 } else {
1818                                         start [0] = start [0] - 1;
1819                                 }
1820                                 start [0] = Math.max (start [0], 0);
1821                         }
1822                         break;
1823                 case 0x7F:      /* Del */
1824                         if (start [0] == end [0]) {
1825                                 int length = OS.GetWindowTextLength (handle);
1826                                 if (start [0] == length) return true;
1827                                 int line = (int)OS.SendMessage (handle, OS.EM_LINEFROMCHAR, end [0], 0);
1828                                 int lineStart = (int)OS.SendMessage (handle, OS.EM_LINEINDEX, line + 1, 0);
1829                                 if (end [0] == lineStart - DELIMITER.length ()) {
1830                                         end [0] = end [0] + DELIMITER.length ();
1831                                 } else {
1832                                         end [0] = end [0] + 1;
1833                                 }
1834                                 end [0] = Math.min (end [0], length);
1835                         }
1836                         break;
1837                 case '\r':      /* Return */
1838                         if ((style & SWT.SINGLE) != 0) return true;
1839                         oldText = DELIMITER;
1840                         break;
1841                 default:        /* Tab and other characters */
1842                         if (key != '\t' && key < 0x20) return true;
1843                         oldText = new String (new char [] {key});
1844                         break;
1845         }
1846         String newText = verifyText (oldText, start [0], end [0], event);
1847         if (newText == null) return false;
1848         if (newText == oldText) return true;
1849         newText = Display.withCrLf (newText);
1850         TCHAR buffer = new TCHAR (getCodePage (), newText, true);
1851         OS.SendMessage (handle, OS.EM_SETSEL, start [0], end [0]);
1852         /*
1853         * Feature in Windows.  When an edit control with ES_MULTILINE
1854         * style that does not have the WS_VSCROLL style is full (i.e.
1855         * there is no space at the end to draw any more characters),
1856         * EM_REPLACESEL sends a WM_CHAR with a backspace character
1857         * to remove any further text that is added.  This is an
1858         * implementation detail of the edit control that is unexpected
1859         * and can cause endless recursion when EM_REPLACESEL is sent
1860         * from a WM_CHAR handler.  The fix is to ignore calling the
1861         * handler from WM_CHAR.
1862         */
1863         ignoreCharacter = true;
1864         OS.SendMessage (handle, OS.EM_REPLACESEL, 0, buffer);
1865         ignoreCharacter = false;
1866         return false;
1867 }
1868
1869 @Override
1870 void setBackgroundImage (long hBitmap) {
1871         int flags = OS.RDW_ERASE | OS.RDW_ALLCHILDREN | OS.RDW_INVALIDATE;
1872         OS.RedrawWindow (handle, null, 0, flags);
1873 }
1874
1875 @Override
1876 void setBackgroundPixel (int pixel) {
1877         int flags = OS.RDW_ERASE | OS.RDW_ALLCHILDREN | OS.RDW_INVALIDATE;
1878         OS.RedrawWindow (handle, null, 0, flags);
1879 }
1880
1881 @Override
1882 void setBoundsInPixels (int x, int y, int width, int height, int flags) {
1883         /*
1884         * Feature in Windows.  When the caret is moved,
1885         * the text widget scrolls to show the new location.
1886         * This means that the text widget may be scrolled
1887         * to the right in order to show the caret when the
1888         * widget is not large enough to show both the caret
1889         * location and all the text.  Unfortunately, when
1890         * the text widget is resized such that all the text
1891         * and the caret could be visible, Windows does not
1892         * scroll the widget back.  The fix is to resize the
1893         * text widget, set the selection to the start of the
1894         * text and then restore the selection.  This will
1895         * cause the text widget compute the correct scroll
1896         * position.
1897         */
1898         if ((flags & OS.SWP_NOSIZE) == 0 && width != 0) {
1899                 RECT rect = new RECT ();
1900                 OS.GetWindowRect (handle, rect);
1901                 long margins = OS.SendMessage (handle, OS.EM_GETMARGINS, 0, 0);
1902                 int marginWidth = OS.LOWORD (margins) + OS.HIWORD (margins);
1903                 if (rect.right - rect.left <= marginWidth) {
1904                         int [] start = new int [1], end = new int [1];
1905                         OS.SendMessage (handle, OS.EM_GETSEL, start, end);
1906                         if (start [0] != 0 || end [0] != 0) {
1907                                 OS.SetWindowPos (handle, 0, x, y, width, height, flags);
1908                                 OS.SendMessage (handle, OS.EM_SETSEL, 0, 0);
1909                                 OS.SendMessage (handle, OS.EM_SETSEL, start [0], end [0]);
1910                                 return;
1911                         }
1912                 }
1913         }
1914         super.setBoundsInPixels (x, y, width, height, flags);
1915
1916         /*
1917         * Bug in Windows. If the client area height is smaller than
1918         * the font height, then the multi-line text widget does not
1919         * update the formatting rectangle when resized. The fix is to
1920         * detect this case and explicitly set the formatting rectangle.
1921         */
1922         if ((flags & OS.SWP_NOSIZE) == 0) {
1923                 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
1924                 if ((bits & OS.ES_MULTILINE) != 0) {
1925                         long newFont, oldFont = 0;
1926                         long hDC = OS.GetDC (handle);
1927                         newFont = OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
1928                         if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
1929                         TEXTMETRIC tm = new TEXTMETRIC ();
1930                         OS.GetTextMetrics (hDC, tm);
1931                         if (newFont != 0) OS.SelectObject (hDC, oldFont);
1932                         OS.ReleaseDC (handle, hDC);
1933                         RECT rect = new RECT();
1934                         OS.GetClientRect (handle, rect);
1935                         if ((rect.bottom - rect.top) < tm.tmHeight) {
1936                                 long margins = OS.SendMessage (handle, OS.EM_GETMARGINS, 0, 0);
1937                                 rect.left += OS.LOWORD (margins);
1938                                 rect.right -= OS.HIWORD (margins);
1939                                 rect.top = 0;
1940                                 rect.bottom = tm.tmHeight;
1941                                 OS.SendMessage (handle, OS.EM_SETRECT, 0, rect);
1942                         }
1943                 }
1944         }
1945 }
1946
1947 @Override
1948 void setDefaultFont () {
1949         super.setDefaultFont ();
1950         setMargins ();
1951 }
1952
1953 /**
1954  * Sets the double click enabled flag.
1955  * <p>
1956  * The double click flag enables or disables the
1957  * default action of the text widget when the user
1958  * double clicks.
1959  * </p><p>
1960  * Note: This operation is a hint and is not supported on
1961  * platforms that do not have this concept.
1962  * </p>
1963  *
1964  * @param doubleClick the new double click flag
1965  *
1966  * @exception SWTException <ul>
1967  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1968  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1969  * </ul>
1970  */
1971 public void setDoubleClickEnabled (boolean doubleClick) {
1972         checkWidget ();
1973         this.doubleClick = doubleClick;
1974 }
1975
1976 /**
1977  * Sets the echo character.
1978  * <p>
1979  * The echo character is the character that is
1980  * displayed when the user enters text or the
1981  * text is changed by the programmer. Setting
1982  * the echo character to '\0' clears the echo
1983  * character and redraws the original text.
1984  * If for any reason the echo character is invalid,
1985  * or if the platform does not allow modification
1986  * of the echo character, the default echo character
1987  * for the platform is used.
1988  * </p>
1989  *
1990  * @param echo the new echo character
1991  *
1992  * @exception SWTException <ul>
1993  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1994  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1995  * </ul>
1996  */
1997 public void setEchoChar (char echo) {
1998         checkWidget ();
1999         if ((style & SWT.MULTI) != 0) return;
2000         allowPasswordChar = true;
2001         OS.SendMessage (handle, OS.EM_SETPASSWORDCHAR, echo, 0);
2002         allowPasswordChar = false;
2003         /*
2004         * Bug in Windows.  When the password character is changed,
2005         * Windows does not redraw to show the new password character.
2006         * The fix is to force a redraw when the character is set.
2007         */
2008         OS.InvalidateRect (handle, null, true);
2009 }
2010
2011 /**
2012  * Sets the editable state.
2013  *
2014  * @param editable the new editable state
2015  *
2016  * @exception SWTException <ul>
2017  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2018  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2019  * </ul>
2020  */
2021 public void setEditable (boolean editable) {
2022         checkWidget ();
2023         style &= ~SWT.READ_ONLY;
2024         if (!editable) style |= SWT.READ_ONLY;
2025         OS.SendMessage (handle, OS.EM_SETREADONLY, editable ? 0 : 1, 0);
2026 }
2027
2028 @Override
2029 public void setFont (Font font) {
2030         checkWidget ();
2031         super.setFont (font);
2032         setTabStops (tabs);
2033         setMargins ();
2034 }
2035
2036 void setMargins () {
2037         if ((style & SWT.SEARCH) != 0) {
2038                 int flags = 0;
2039                 int fLeading = (style & SWT.LEFT_TO_RIGHT) != 0 ? OS.EC_LEFTMARGIN : OS.EC_RIGHTMARGIN;
2040                 int fTrailing = (style & SWT.LEFT_TO_RIGHT) != 0 ? OS.EC_RIGHTMARGIN : OS.EC_LEFTMARGIN;
2041                 if ((style & SWT.ICON_SEARCH) != 0) flags |= fLeading;
2042                 if ((style & SWT.ICON_CANCEL) != 0) flags |= fTrailing;
2043                 if (flags != 0) {
2044                         int iconWidth = OS.GetSystemMetrics (OS.SM_CXSMICON);
2045                         OS.SendMessage (handle, OS.EM_SETMARGINS, flags, OS.MAKELPARAM(iconWidth, iconWidth));
2046                 }
2047         }
2048 }
2049
2050 /**
2051  * Sets the widget message. The message text is displayed
2052  * as a hint for the user, indicating the purpose of the field.
2053  * <p>
2054  * Typically this is used in conjunction with <code>SWT.SEARCH</code>.
2055  * </p>
2056  *
2057  * @param message the new message
2058  *
2059  * @exception IllegalArgumentException <ul>
2060  *    <li>ERROR_NULL_ARGUMENT - if the message is null</li>
2061  * </ul>
2062  * @exception SWTException <ul>
2063  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2064  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2065  * </ul>
2066  *
2067  * @since 3.3
2068  */
2069 public void setMessage (String message) {
2070         checkWidget ();
2071         if (message == null) error (SWT.ERROR_NULL_ARGUMENT);
2072         this.message = message;
2073         int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
2074         if ((bits & OS.ES_MULTILINE) == 0) {
2075                 int length = message.length ();
2076                 char [] chars = new char [length + 1];
2077                 message.getChars(0, length, chars, 0);
2078                 OS.SendMessage (handle, OS.EM_SETCUEBANNER, 0, chars);
2079         }
2080 }
2081
2082 /**
2083  * Sets the orientation of the receiver, which must be one
2084  * of the constants <code>SWT.LEFT_TO_RIGHT</code> or <code>SWT.RIGHT_TO_LEFT</code>.
2085  * <p>
2086  * Note: This operation is a hint and is not supported on
2087  * platforms that do not have this concept.
2088  * </p>
2089  *
2090  * @param orientation new orientation style
2091  *
2092  * @exception SWTException <ul>
2093  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2094  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2095  * </ul>
2096  *
2097  * @since 2.1.2
2098  */
2099 @Override
2100 public void setOrientation (int orientation) {
2101         super.setOrientation (orientation);
2102 }
2103
2104 /**
2105  * Sets the selection.
2106  * <p>
2107  * Indexing is zero based.  The range of
2108  * a selection is from 0..N where N is
2109  * the number of characters in the widget.
2110  * </p><p>
2111  * Text selections are specified in terms of
2112  * caret positions.  In a text widget that
2113  * contains N characters, there are N+1 caret
2114  * positions, ranging from 0..N.  This differs
2115  * from other functions that address character
2116  * position such as getText () that use the
2117  * regular array indexing rules.
2118  * </p>
2119  *
2120  * @param start new caret position
2121  *
2122  * @exception SWTException <ul>
2123  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2124  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2125  * </ul>
2126  */
2127 public void setSelection (int start) {
2128         checkWidget ();
2129         start = translateOffset (start);
2130         OS.SendMessage (handle, OS.EM_SETSEL, start, start);
2131         OS.SendMessage (handle, OS.EM_SCROLLCARET, 0, 0);
2132 }
2133
2134 /**
2135  * Sets the selection to the range specified
2136  * by the given start and end indices.
2137  * <p>
2138  * Indexing is zero based.  The range of
2139  * a selection is from 0..N where N is
2140  * the number of characters in the widget.
2141  * </p><p>
2142  * Text selections are specified in terms of
2143  * caret positions.  In a text widget that
2144  * contains N characters, there are N+1 caret
2145  * positions, ranging from 0..N.  This differs
2146  * from other functions that address character
2147  * position such as getText () that use the
2148  * usual array indexing rules.
2149  * </p>
2150  *
2151  * @param start the start of the range
2152  * @param end the end of the range
2153  *
2154  * @exception SWTException <ul>
2155  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2156  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2157  * </ul>
2158  */
2159 public void setSelection (int start, int end) {
2160         checkWidget ();
2161         start = translateOffset (start);
2162         end = translateOffset (end);
2163         OS.SendMessage (handle, OS.EM_SETSEL, start, end);
2164         OS.SendMessage (handle, OS.EM_SCROLLCARET, 0, 0);
2165 }
2166
2167 @Override
2168 public void setRedraw (boolean redraw) {
2169         checkWidget ();
2170         super.setRedraw (redraw);
2171         /*
2172         * Feature in Windows.  When WM_SETREDRAW is used to turn
2173         * redraw off, the edit control is not scrolled to show the
2174         * i-beam.  The fix is to detect that the i-beam has moved
2175         * while redraw is turned off and force it to be visible
2176         * when redraw is restored.
2177         */
2178         if (!getDrawing ()) return;
2179         int [] start = new int [1], end = new int [1];
2180         OS.SendMessage (handle, OS.EM_GETSEL, start, end);
2181         if (!redraw) {
2182                 oldStart = start [0];  oldEnd = end [0];
2183         } else {
2184                 if (oldStart == start [0] && oldEnd == end [0]) return;
2185                 OS.SendMessage (handle, OS.EM_SCROLLCARET, 0, 0);
2186         }
2187 }
2188
2189 /**
2190  * Sets the selection to the range specified
2191  * by the given point, where the x coordinate
2192  * represents the start index and the y coordinate
2193  * represents the end index.
2194  * <p>
2195  * Indexing is zero based.  The range of
2196  * a selection is from 0..N where N is
2197  * the number of characters in the widget.
2198  * </p><p>
2199  * Text selections are specified in terms of
2200  * caret positions.  In a text widget that
2201  * contains N characters, there are N+1 caret
2202  * positions, ranging from 0..N.  This differs
2203  * from other functions that address character
2204  * position such as getText () that use the
2205  * usual array indexing rules.
2206  * </p>
2207  *
2208  * @param selection the point
2209  *
2210  * @exception IllegalArgumentException <ul>
2211  *    <li>ERROR_NULL_ARGUMENT - if the point is null</li>
2212  * </ul>
2213  * @exception SWTException <ul>
2214  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2215  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2216  * </ul>
2217  */
2218 public void setSelection (Point selection) {
2219         checkWidget ();
2220         if (selection == null) error (SWT.ERROR_NULL_ARGUMENT);
2221         setSelection (selection.x, selection.y);
2222 }
2223
2224 /**
2225  * Sets the number of tabs.
2226  * <p>
2227  * Tab stop spacing is specified in terms of the
2228  * space (' ') character.  The width of a single
2229  * tab stop is the pixel width of the spaces.
2230  * </p>
2231  *
2232  * @param tabs the number of tabs
2233  *
2234  * @exception SWTException <ul>
2235  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2236  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2237  * </ul>
2238  */
2239 public void setTabs (int tabs) {
2240         checkWidget ();
2241         if (tabs < 0) return;
2242         setTabStops (this.tabs = tabs);
2243 }
2244
2245 void setTabStops (int tabs) {
2246         /*
2247         * Feature in Windows.  Windows expects the tab spacing in
2248         * dialog units so we must convert from space widths.  Due
2249         * to round off error, the tab spacing may not be the exact
2250         * number of space widths, depending on the font.
2251         */
2252         int width = (getTabWidth (tabs) * 4) / OS.LOWORD (OS.GetDialogBaseUnits ());
2253         OS.SendMessage (handle, OS.EM_SETTABSTOPS, 1, new int [] {width});
2254 }
2255
2256 /**
2257  * Sets the contents of the receiver to the given string. If the receiver has style
2258  * SINGLE and the argument contains multiple lines of text, the result of this
2259  * operation is undefined and may vary from platform to platform.
2260  * <p>
2261  * Note: If control characters like '\n', '\t' etc. are used
2262  * in the string, then the behavior is platform dependent.
2263  * </p>
2264  * @param string the new text
2265  *
2266  * @exception IllegalArgumentException <ul>
2267  *    <li>ERROR_NULL_ARGUMENT - if the string is null</li>
2268  * </ul>
2269  * @exception SWTException <ul>
2270  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2271  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2272  * </ul>
2273  */
2274 public void setText (String string) {
2275         checkWidget ();
2276         if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
2277         string = Display.withCrLf (string);
2278         if (hooks (SWT.Verify) || filters (SWT.Verify)) {
2279                 int length = OS.GetWindowTextLength (handle);
2280                 string = verifyText (string, 0, length, null);
2281                 if (string == null) return;
2282         }
2283         clearSegments (false);
2284         int limit = (int)OS.SendMessage (handle, OS.EM_GETLIMITTEXT, 0, 0) & 0x7FFFFFFF;
2285         if (string.length () > limit) string = string.substring (0, limit);
2286         TCHAR buffer = new TCHAR (getCodePage (), string, true);
2287         OS.SetWindowText (handle, buffer);
2288         if ((state & HAS_AUTO_DIRECTION) != 0) {
2289                 super.updateTextDirection(AUTO_TEXT_DIRECTION);
2290         }
2291         applySegments ();
2292         /*
2293         * Bug in Windows.  When the widget is multi line
2294         * text widget, it does not send a WM_COMMAND with
2295         * control code EN_CHANGE from SetWindowText () to
2296         * notify the application that the text has changed.
2297         * The fix is to send the event.
2298         */
2299         int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
2300         if ((bits & OS.ES_MULTILINE) != 0) {
2301                 sendEvent (SWT.Modify);
2302                 // widget could be disposed at this point
2303         }
2304 }
2305
2306 /**
2307  * Sets the contents of the receiver to the characters in the array. If the receiver
2308  * has style <code>SWT.SINGLE</code> and the argument contains multiple lines of text
2309  * then the result of this operation is undefined and may vary between platforms.
2310  * <p>
2311  * Note: Use this API to prevent the text from being written into a String
2312  * object whose lifecycle is outside of your control. This can help protect
2313  * the text, for example, when the widget is used as a password field.
2314  * However, the text can't be protected if an {@link SWT#Segments} or
2315  * {@link SWT#Verify} listener has been added to the widget.
2316  * </p>
2317  *
2318  * @param text a character array that contains the new text
2319  *
2320  * @exception IllegalArgumentException <ul>
2321  *    <li>ERROR_NULL_ARGUMENT - if the array is null</li>
2322  * </ul>
2323  * @exception SWTException <ul>
2324  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2325  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2326  * </ul>
2327  *
2328  * @see #getTextChars()
2329  *
2330  * @since 3.7
2331  */
2332 public void setTextChars (char[] text) {
2333         checkWidget ();
2334         if (text == null) error (SWT.ERROR_NULL_ARGUMENT);
2335         text = Display.withCrLf (text);
2336         if (hooks (SWT.Verify) || filters (SWT.Verify)) {
2337                 int length = OS.GetWindowTextLength (handle);
2338                 String string = verifyText (new String (text), 0, length, null);
2339                 if (string == null) return;
2340                 text = new char [string.length()];
2341                 string.getChars (0, text.length, text, 0);
2342         }
2343         clearSegments (false);
2344         int limit = (int)OS.SendMessage (handle, OS.EM_GETLIMITTEXT, 0, 0) & 0x7FFFFFFF;
2345         if (text.length > limit) {
2346                 char [] temp = new char [limit];
2347                 for (int i = 0; i < limit; i++) temp [i] = text [i];
2348                 text = temp;
2349         }
2350         TCHAR buffer = new TCHAR (getCodePage (), text, true);
2351         OS.SetWindowText (handle, buffer);
2352         buffer.clear ();
2353         if ((state & HAS_AUTO_DIRECTION) != 0) {
2354                 super.updateTextDirection (AUTO_TEXT_DIRECTION);
2355         }
2356         applySegments ();
2357         /*
2358         * Bug in Windows.  When the widget is multi line
2359         * text widget, it does not send a WM_COMMAND with
2360         * control code EN_CHANGE from SetWindowText () to
2361         * notify the application that the text has changed.
2362         * The fix is to send the event.
2363         */
2364         int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
2365         if ((bits & OS.ES_MULTILINE) != 0) {
2366                 sendEvent (SWT.Modify);
2367                 // widget could be disposed at this point
2368         }
2369 }
2370
2371 /**
2372  * Sets the maximum number of characters that the receiver
2373  * is capable of holding to be the argument.
2374  * <p>
2375  * Instead of trying to set the text limit to zero, consider
2376  * creating a read-only text widget.
2377  * </p><p>
2378  * To reset this value to the default, use <code>setTextLimit(Text.LIMIT)</code>.
2379  * Specifying a limit value larger than <code>Text.LIMIT</code> sets the
2380  * receiver's limit to <code>Text.LIMIT</code>.
2381  * </p>
2382  *
2383  * @param limit new text limit
2384  *
2385  * @exception IllegalArgumentException <ul>
2386  *    <li>ERROR_CANNOT_BE_ZERO - if the limit is zero</li>
2387  * </ul>
2388  * @exception SWTException <ul>
2389  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2390  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2391  * </ul>
2392  *
2393  * @see #LIMIT
2394  */
2395 public void setTextLimit (int limit) {
2396         checkWidget ();
2397         if (limit == 0) error (SWT.ERROR_CANNOT_BE_ZERO);
2398         if (segments != null && limit > 0) {
2399                 OS.SendMessage (handle, OS.EM_SETLIMITTEXT, limit + Math.min (segments.length, LIMIT - limit), 0);
2400         } else {
2401                 OS.SendMessage (handle, OS.EM_SETLIMITTEXT, limit, 0);
2402         }
2403 }
2404
2405 /**
2406  * Sets the zero-relative index of the line which is currently
2407  * at the top of the receiver. This index can change when lines
2408  * are scrolled or new lines are added and removed.
2409  *
2410  * @param index the index of the top item
2411  *
2412  * @exception SWTException <ul>
2413  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2414  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2415  * </ul>
2416  */
2417 public void setTopIndex (int index) {
2418         checkWidget ();
2419         if ((style & SWT.SINGLE) != 0) return;
2420         int count = (int)OS.SendMessage (handle, OS.EM_GETLINECOUNT, 0, 0);
2421         index = Math.min (Math.max (index, 0), count - 1);
2422         int topIndex = (int)OS.SendMessage (handle, OS.EM_GETFIRSTVISIBLELINE, 0, 0);
2423         OS.SendMessage (handle, OS.EM_LINESCROLL, 0, index - topIndex);
2424 }
2425
2426 /**
2427  * Shows the selection.
2428  * <p>
2429  * If the selection is already showing
2430  * in the receiver, this method simply returns.  Otherwise,
2431  * lines are scrolled until the selection is visible.
2432  * </p>
2433  *
2434  * @exception SWTException <ul>
2435  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
2436  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
2437  * </ul>
2438  */
2439 public void showSelection () {
2440         checkWidget ();
2441         OS.SendMessage (handle, OS.EM_SCROLLCARET, 0, 0);
2442 }
2443
2444 int translateOffset (int offset) {
2445         if (segments == null) return offset;
2446         for (int i = 0, nSegments = segments.length; i < nSegments && offset - i >= segments [i]; i++) {
2447                 offset++;
2448         }
2449         return offset;
2450 }
2451
2452 int untranslateOffset (int offset) {
2453         if (segments == null) return offset;
2454         for (int i = 0, nSegments = segments.length; i < nSegments && offset > segments [i]; i++) {
2455                 offset--;
2456         }
2457         return offset;
2458 }
2459
2460 @Override
2461 void updateMenuLocation (Event event) {
2462         Point point = display.mapInPixels (this, null, getCaretLocationInPixels ());
2463         event.setLocationInPixels(point.x, point.y + getLineHeightInPixels ());
2464 }
2465
2466 @Override
2467 void updateOrientation (){
2468         int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
2469         if ((style & SWT.RIGHT_TO_LEFT) != 0) {
2470                 bits |= OS.WS_EX_RTLREADING | OS.WS_EX_LEFTSCROLLBAR;
2471         } else {
2472                 bits &= ~(OS.WS_EX_RTLREADING | OS.WS_EX_LEFTSCROLLBAR);
2473         }
2474         OS.SetWindowLong (handle, OS.GWL_EXSTYLE, bits);
2475         fixAlignment ();
2476 }
2477
2478 @Override
2479 boolean updateTextDirection(int textDirection) {
2480         if (super.updateTextDirection(textDirection)) {
2481                 clearSegments (true);
2482                 applySegments ();
2483                 return true;
2484         }
2485         return false;
2486 }
2487
2488 String verifyText (String string, int start, int end, Event keyEvent) {
2489         if (ignoreVerify) return string;
2490         Event event = new Event ();
2491         event.text = string;
2492         event.start = start;
2493         event.end = end;
2494         if (keyEvent != null) {
2495                 event.character = keyEvent.character;
2496                 event.keyCode = keyEvent.keyCode;
2497                 event.stateMask = keyEvent.stateMask;
2498         }
2499         event.start = untranslateOffset (event.start);
2500         event.end = untranslateOffset (event.end);
2501
2502         /*
2503         * It is possible (but unlikely), that application
2504         * code could have disposed the widget in the verify
2505         * event.  If this happens, answer null to cancel
2506         * the operation.
2507         */
2508         sendEvent (SWT.Verify, event);
2509         if (!event.doit || isDisposed ()) return null;
2510         return event.text;
2511 }
2512
2513 @Override
2514 int widgetStyle () {
2515         int bits = super.widgetStyle () | OS.ES_AUTOHSCROLL;
2516         if ((style & SWT.PASSWORD) != 0) bits |= OS.ES_PASSWORD;
2517         if ((style & SWT.CENTER) != 0) bits |= OS.ES_CENTER;
2518         if ((style & SWT.RIGHT) != 0) bits |= OS.ES_RIGHT;
2519         if ((style & SWT.READ_ONLY) != 0) bits |= OS.ES_READONLY;
2520         if ((style & SWT.SEARCH) != 0) bits |= OS.WS_CLIPCHILDREN;
2521         if ((style & SWT.SINGLE) != 0) {
2522                 /*
2523                 * Feature in Windows.  When a text control is read-only,
2524                 * uses COLOR_3DFACE for the background .  If the text
2525                 * controls single-line and is within a tab folder or
2526                 * some other themed control, using WM_ERASEBKGND and
2527                 * WM_CTRCOLOR to draw the theme background results in
2528                 * pixel corruption.  The fix is to use an ES_MULTILINE
2529                 * text control instead.
2530                 * Refer Bug438901:- ES_MULTILINE doesn't apply for:
2531                 * SWT.PASSWORD | SWT.READ_ONLY style combination.
2532                 */
2533                 if ((style & SWT.READ_ONLY) != 0) {
2534                         if ((style & (SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.PASSWORD)) == 0) {
2535                                 if (OS.IsAppThemed ()) {
2536                                         bits |= OS.ES_MULTILINE;
2537                                 }
2538                         }
2539                 }
2540                 return bits;
2541         }
2542         bits |= OS.ES_MULTILINE | OS.ES_NOHIDESEL | OS.ES_AUTOVSCROLL;
2543         if ((style & SWT.WRAP) != 0) bits &= ~(OS.WS_HSCROLL | OS.ES_AUTOHSCROLL);
2544         return bits;
2545 }
2546
2547 @Override
2548 TCHAR windowClass () {
2549         return EditClass;
2550 }
2551
2552 @Override
2553 long windowProc () {
2554         return EditProc;
2555 }
2556
2557 @Override
2558 long windowProc (long hwnd, int msg, long wParam, long lParam) {
2559         boolean processSegments = hooks (SWT.Segments) || filters (SWT.Segments), redraw = false, updateDirection = (state & HAS_AUTO_DIRECTION) != 0;
2560         long code;
2561         if (processSegments || updateDirection) {
2562                 switch (msg) {
2563                         case OS.EM_CANUNDO:
2564                                 if (processSegments) return 0;
2565                                 updateDirection = false;
2566                                 break;
2567                         case OS.EM_UNDO:
2568                         case OS.WM_UNDO:
2569                                 if (processSegments) return 0;
2570                                 break;
2571                         case OS.WM_KEYDOWN:
2572                                 if (wParam != OS.VK_DELETE) {
2573                                         processSegments = updateDirection = false;
2574                                 }
2575                                 break;
2576                         case OS.WM_COPY:
2577                                 processSegments = segments != null;
2578                                 updateDirection = false;
2579                                 break;
2580                         case OS.WM_CHAR:
2581                                 if (ignoreCharacter || OS.GetKeyState (OS.VK_CONTROL) < 0 || OS.GetKeyState (OS.VK_MENU) < 0) {
2582                                         processSegments = updateDirection = false;
2583                                 }
2584                                 break;
2585                         case OS.WM_PASTE:
2586                         case OS.WM_CUT:
2587                         case OS.WM_CLEAR:
2588                                 break;
2589                         default:
2590                                 processSegments = updateDirection = false;
2591                 }
2592         }
2593         if (processSegments) {
2594                 if (getDrawing () && OS.IsWindowVisible (handle)) {
2595                         redraw = true;
2596                         OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
2597                 }
2598                 clearSegments (true);
2599         }
2600         if (msg == OS.EM_UNDO) {
2601                 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
2602                 if ((bits & OS.ES_MULTILINE) == 0) {
2603                         LRESULT result = wmClipboard (OS.EM_UNDO, wParam, lParam);
2604                         if (result != null) return result.value;
2605                         return callWindowProc (hwnd, OS.EM_UNDO, wParam, lParam);
2606                 }
2607         }
2608         if (msg == OS.EM_SETPASSWORDCHAR) {
2609                 if (!allowPasswordChar) {
2610                         return 1;
2611                 }
2612         }
2613         if (msg == Display.SWT_RESTORECARET) {
2614                 callWindowProc (hwnd, OS.WM_KILLFOCUS, 0, 0);
2615                 callWindowProc (hwnd, OS.WM_SETFOCUS, 0, 0);
2616                 return 1;
2617         }
2618         code = super.windowProc (hwnd, msg, wParam, lParam);
2619         if (updateDirection) {
2620                 super.updateTextDirection (AUTO_TEXT_DIRECTION);
2621         }
2622         if (processSegments) {
2623                 applySegments ();
2624                 if (redraw) {
2625                         OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
2626                         OS.InvalidateRect (handle, null, true);
2627                 }
2628                 OS.SendMessage (handle, OS.EM_SCROLLCARET, 0, 0);
2629         }
2630         return code;
2631 }
2632
2633 @Override
2634 LRESULT WM_CHAR (long wParam, long lParam) {
2635         if (ignoreCharacter) return null;
2636         LRESULT result = super.WM_CHAR (wParam, lParam);
2637         if (result != null) return result;
2638
2639         /*
2640         * Bug in Windows.  When the user types CTRL and BS
2641         * in an edit control, a DEL character is generated.
2642         * Rather than deleting the text, the DEL character
2643         * is inserted into the control.  The fix is to detect
2644         * this case and not call the window proc.
2645         */
2646         switch ((int)wParam) {
2647                 case SWT.DEL:
2648                         if (OS.GetKeyState (OS.VK_CONTROL) < 0) {
2649                                 if ((style & SWT.READ_ONLY) != 0 || (style & SWT.PASSWORD) != 0) return LRESULT.ZERO;
2650                                 Point selection = getSelection ();
2651                                 int x = selection.x;
2652                                 int y = selection.y;
2653                                 if (x == y) {
2654                                         String actText = getText (0, x - 1);
2655                                         java.util.regex.Matcher m = CTRL_BS_PATTERN.matcher (actText);
2656                                         if (m.find ()) {
2657                                                 x = m.start ();
2658                                                 y = m.end ();
2659                                                 OS.SendMessage (handle, OS.EM_SETSEL, x, y);
2660                                         }
2661                                 }
2662                                 if (x < y) {
2663                                         /*
2664                                         * Instead of setting the new text directly we send the replace selection event to
2665                                         * guarantee that the action is pushed to the undo buffer.
2666                                         */
2667                                         OS.SendMessage (handle, OS.EM_REPLACESEL, 1, 0);
2668                                 }
2669                                 return LRESULT.ZERO;
2670                         }
2671         }
2672
2673         /*
2674         * Feature in Windows.  For some reason, when the
2675         * widget is a single line text widget, when the
2676         * user presses tab, return or escape, Windows beeps.
2677         * The fix is to look for these keys and not call
2678         * the window proc.
2679         */
2680         if ((style & SWT.SINGLE) != 0) {
2681                 switch ((int)wParam) {
2682                         case SWT.CR:
2683                                 sendSelectionEvent (SWT.DefaultSelection);
2684                                 // FALL THROUGH
2685                         case SWT.TAB:
2686                         case SWT.ESC: return LRESULT.ZERO;
2687                 }
2688         }
2689         return result;
2690 }
2691
2692 @Override
2693 LRESULT WM_CLEAR (long wParam, long lParam) {
2694         LRESULT result = super.WM_CLEAR (wParam, lParam);
2695         if (result != null) return result;
2696         return wmClipboard (OS.WM_CLEAR, wParam, lParam);
2697 }
2698
2699 @Override
2700 LRESULT WM_CUT (long wParam, long lParam) {
2701         LRESULT result = super.WM_CUT (wParam, lParam);
2702         if (result != null) return result;
2703         return wmClipboard (OS.WM_CUT, wParam, lParam);
2704 }
2705
2706 @Override
2707 LRESULT WM_DRAWITEM (long wParam, long lParam) {
2708         DRAWITEMSTRUCT struct = new DRAWITEMSTRUCT ();
2709         OS.MoveMemory (struct, lParam, DRAWITEMSTRUCT.sizeof);
2710         RECT rect = new RECT ();
2711         OS.SetRect (rect, struct.left, struct.top, struct.right, struct.bottom);
2712         POINT pt = new POINT ();
2713         OS.MapWindowPoints (struct.hwndItem, handle, pt, 1);
2714         drawBackground (struct.hDC, rect, -1, pt.x, pt.y);
2715         if (struct.hwndItem == hwndCancel && struct.hwndItem == hwndActive && OS.IsAppThemed()) {
2716                 int state = OS.GetKeyState (OS.VK_LBUTTON) < 0 ? OS.PBS_PRESSED : OS.PBS_HOT;
2717                 OS.DrawThemeBackground (display.hButtonTheme (), struct.hDC, OS.BP_PUSHBUTTON, state, rect, null);
2718         }
2719         long hIcon = (struct.hwndItem == hwndSearch) ? display.hIconSearch : display.hIconCancel;
2720         int y = (rect.bottom - rect.right) / 2;
2721         OS.DrawIconEx (struct.hDC, 0, y, hIcon, 0, 0, 0, 0, OS.DI_NORMAL);
2722         return LRESULT.ONE;
2723 }
2724
2725 @Override
2726 LRESULT WM_ERASEBKGND (long wParam, long lParam) {
2727         LRESULT result = super.WM_ERASEBKGND (wParam, lParam);
2728         if ((style & SWT.READ_ONLY) != 0) {
2729                 if ((style & (SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL)) == 0) {
2730                         int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
2731                         if ((bits & OS.ES_MULTILINE) != 0) {
2732                                 Control control = findBackgroundControl ();
2733                                 if (control == null && background == -1) {
2734                                         if ((state & THEME_BACKGROUND) != 0) {
2735                                                 if (OS.IsAppThemed ()) {
2736                                                         control = findThemeControl ();
2737                                                         if (control != null) {
2738                                                                 RECT rect = new RECT ();
2739                                                                 OS.GetClientRect (handle, rect);
2740                                                                 fillThemeBackground (wParam, control, rect);
2741                                                                 return LRESULT.ONE;
2742                                                         }
2743                                                 }
2744                                         }
2745                                 }
2746                         }
2747                 }
2748         }
2749         return result;
2750 }
2751
2752 @Override
2753 LRESULT WM_GETDLGCODE (long wParam, long lParam) {
2754         LRESULT result = super.WM_GETDLGCODE (wParam, lParam);
2755         if (result != null) return result;
2756
2757         /*
2758         * Feature in Windows.  Despite the fact that the
2759         * edit control is read only, it still returns a
2760         * dialog code indicating that it wants all keys.
2761         * The fix is to detect this case and clear the bits.
2762         *
2763         * NOTE: A read only edit control processes arrow keys
2764         * so DLGC_WANTARROWS should not be cleared.
2765         */
2766         if ((style & SWT.READ_ONLY) != 0) {
2767                 long code = callWindowProc (handle, OS.WM_GETDLGCODE, wParam, lParam);
2768                 code &= ~(OS.DLGC_WANTALLKEYS | OS.DLGC_WANTTAB);
2769                 return new LRESULT (code);
2770         }
2771         return null;
2772 }
2773
2774 @Override
2775 LRESULT WM_GETOBJECT (long wParam, long lParam) {
2776         /*
2777         * Ensure that there is an accessible object created for this
2778         * control because support for search text accessibility is
2779         * implemented in the accessibility package.
2780         */
2781         if ((style & SWT.SEARCH) != 0) {
2782                 if (accessible == null) accessible = new_Accessible (this);
2783         }
2784         return super.WM_GETOBJECT (wParam, lParam);
2785 }
2786
2787 @Override
2788 LRESULT WM_IME_CHAR (long wParam, long lParam) {
2789
2790         /* Process a DBCS character */
2791         Display display = this.display;
2792         display.lastKey = 0;
2793         display.lastAscii = (int)wParam;
2794         display.lastVirtual = display.lastNull = display.lastDead = false;
2795         if (!sendKeyEvent (SWT.KeyDown, OS.WM_IME_CHAR, wParam, lParam)) {
2796                 return LRESULT.ZERO;
2797         }
2798
2799         /*
2800         * Feature in Windows.  The Windows text widget uses
2801         * two 2 WM_CHAR's to process a DBCS key instead of
2802         * using WM_IME_CHAR.  The fix is to allow the text
2803         * widget to get the WM_CHAR's but ignore sending
2804         * them to the application.
2805         */
2806         ignoreCharacter = true;
2807         long result = callWindowProc (handle, OS.WM_IME_CHAR, wParam, lParam);
2808         MSG msg = new MSG ();
2809         int flags = OS.PM_REMOVE | OS.PM_NOYIELD | OS.PM_QS_INPUT | OS.PM_QS_POSTMESSAGE;
2810         while (OS.PeekMessage (msg, handle, OS.WM_CHAR, OS.WM_CHAR, flags)) {
2811                 OS.TranslateMessage (msg);
2812                 OS.DispatchMessage (msg);
2813         }
2814         ignoreCharacter = false;
2815
2816         sendKeyEvent (SWT.KeyUp, OS.WM_IME_CHAR, wParam, lParam);
2817         // widget could be disposed at this point
2818         display.lastKey = display.lastAscii = 0;
2819         return new LRESULT (result);
2820 }
2821
2822 @Override
2823 LRESULT WM_LBUTTONDBLCLK (long wParam, long lParam) {
2824         /*
2825         * Prevent Windows from processing WM_LBUTTONDBLCLK
2826         * when double clicking behavior is disabled by not
2827         * calling the window proc.
2828         */
2829         LRESULT result = null;
2830         sendMouseEvent (SWT.MouseDown, 1, handle, OS.WM_LBUTTONDOWN, wParam, lParam);
2831         if (!sendMouseEvent (SWT.MouseDoubleClick, 1, handle, OS.WM_LBUTTONDBLCLK, wParam, lParam)) {
2832                 result = LRESULT.ZERO;
2833         }
2834         if (!display.captureChanged && !isDisposed ()) {
2835                 if (OS.GetCapture () != handle) OS.SetCapture (handle);
2836         }
2837         if (!doubleClick) return LRESULT.ZERO;
2838
2839         /*
2840         * Bug in Windows.  When the last line of text in the
2841         * widget is double clicked and the line is empty, Windows
2842         * hides the i-beam then moves it to the first line in
2843         * the widget but does not scroll to show the user.
2844         * If the user types without clicking the mouse, invalid
2845         * characters are displayed at the end of each line of
2846         * text in the widget.  The fix is to detect this case
2847         * and avoid calling the window proc.
2848         */
2849         int [] start = new int [1], end = new int [1];
2850         OS.SendMessage (handle, OS.EM_GETSEL, start, end);
2851         if (start [0] == end [0]) {
2852                 int length = OS.GetWindowTextLength (handle);
2853                 if (length == start [0]) {
2854                         int code = (int)OS.SendMessage (handle, OS.EM_LINELENGTH, length, 0);
2855                         if (code == 0) return LRESULT.ZERO;
2856                 }
2857         }
2858         return result;
2859 }
2860
2861 @Override
2862 LRESULT WM_PASTE (long wParam, long lParam) {
2863         LRESULT result = super.WM_PASTE (wParam, lParam);
2864         if (result != null) return result;
2865         return wmClipboard (OS.WM_PASTE, wParam, lParam);
2866 }
2867
2868 @Override
2869 LRESULT WM_SIZE(long wParam, long lParam) {
2870         LRESULT result = super.WM_SIZE (wParam, lParam);
2871         if (isDisposed ()) return result;
2872         if ((style & SWT.SEARCH) != 0) {
2873                 /* NOTE: EDIT controls don't support mirrored layout. */
2874                 long hwndLeading = (style & SWT.LEFT_TO_RIGHT) != 0 ? hwndSearch : hwndCancel;
2875                 long hwndTrailing = (style & SWT.LEFT_TO_RIGHT) != 0 ? hwndCancel : hwndSearch;
2876                 int width = OS.LOWORD (lParam);
2877                 int height = OS.HIWORD (lParam);
2878                 int iconWidth = OS.GetSystemMetrics (OS.SM_CXSMICON);
2879                 int flags = OS.SWP_NOZORDER | OS.SWP_NOACTIVATE | OS.SWP_NOCOPYBITS;
2880                 if (hwndLeading != 0) OS.SetWindowPos (hwndLeading, 0, 0, 0, iconWidth, height, flags);
2881                 if (hwndTrailing != 0) OS.SetWindowPos (hwndTrailing, 0, width - iconWidth, 0, iconWidth, height, flags);
2882         }
2883         return result;
2884 }
2885
2886 @Override
2887 LRESULT WM_UNDO (long wParam, long lParam) {
2888         LRESULT result = super.WM_UNDO (wParam, lParam);
2889         if (result != null) return result;
2890         return wmClipboard (OS.WM_UNDO, wParam, lParam);
2891 }
2892
2893 LRESULT wmClipboard (int msg, long wParam, long lParam) {
2894         if ((style & SWT.READ_ONLY) != 0) return null;
2895         if (!hooks (SWT.Verify) && !filters (SWT.Verify)) return null;
2896         boolean call = false;
2897         int [] start = new int [1], end = new int [1];
2898         String newText = null;
2899         switch (msg) {
2900                 case OS.WM_CLEAR:
2901                 case OS.WM_CUT:
2902                         OS.SendMessage (handle, OS.EM_GETSEL, start, end);
2903                         if (start [0] != end [0]) {
2904                                 newText = "";
2905                                 call = true;
2906                         }
2907                         break;
2908                 case OS.WM_PASTE:
2909                         OS.SendMessage (handle, OS.EM_GETSEL, start, end);
2910                         newText = getClipboardText ();
2911                         break;
2912                 case OS.EM_UNDO:
2913                 case OS.WM_UNDO:
2914                         if (OS.SendMessage (handle, OS.EM_CANUNDO, 0, 0) != 0) {
2915                                 ignoreModify = ignoreCharacter = true;
2916                                 callWindowProc (handle, msg, wParam, lParam);
2917                                 int length = OS.GetWindowTextLength (handle);
2918                                 int [] newStart = new int [1], newEnd = new int [1];
2919                                 OS.SendMessage (handle, OS.EM_GETSEL, newStart, newEnd);
2920                                 if (length != 0 && newStart [0] != newEnd [0]) {
2921                                         char [] buffer = new char [length + 1];
2922                                         OS.GetWindowText (handle, buffer, length + 1);
2923                                         newText = new String (buffer, newStart [0], newEnd [0] - newStart [0]);
2924                                 } else {
2925                                         newText = "";
2926                                 }
2927                                 callWindowProc (handle, msg, wParam, lParam);
2928                                 OS.SendMessage (handle, OS.EM_GETSEL, start, end);
2929                                 ignoreModify = ignoreCharacter = false;
2930                         }
2931                         break;
2932         }
2933         if (newText != null) {
2934                 String oldText = newText;
2935                 newText = verifyText (newText, start [0], end [0], null);
2936                 if (newText == null) return LRESULT.ZERO;
2937                 if (!newText.equals (oldText)) {
2938                         if (call) {
2939                                 callWindowProc (handle, msg, wParam, lParam);
2940                         }
2941                         newText = Display.withCrLf (newText);
2942                         TCHAR buffer = new TCHAR (getCodePage (), newText, true);
2943                         /*
2944                         * Feature in Windows.  When an edit control with ES_MULTILINE
2945                         * style that does not have the WS_VSCROLL style is full (i.e.
2946                         * there is no space at the end to draw any more characters),
2947                         * EM_REPLACESEL sends a WM_CHAR with a backspace character
2948                         * to remove any further text that is added.  This is an
2949                         * implementation detail of the edit control that is unexpected
2950                         * and can cause endless recursion when EM_REPLACESEL is sent
2951                         * from a WM_CHAR handler.  The fix is to ignore calling the
2952                         * handler from WM_CHAR.
2953                         */
2954                         ignoreCharacter = true;
2955                         OS.SendMessage (handle, OS.EM_REPLACESEL, 0, buffer);
2956                         ignoreCharacter = false;
2957                         return LRESULT.ZERO;
2958                 }
2959         }
2960         if (msg == OS.WM_UNDO) {
2961                 ignoreVerify = ignoreCharacter = true;
2962                 callWindowProc (handle, OS.WM_UNDO, wParam, lParam);
2963                 ignoreVerify = ignoreCharacter = false;
2964                 return LRESULT.ONE;
2965         }
2966         return null;
2967 }
2968
2969 @Override
2970 LRESULT wmColorChild (long wParam, long lParam) {
2971         if ((style & SWT.READ_ONLY) != 0) {
2972                 if ((style & (SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL)) == 0) {
2973                         int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
2974                         if ((bits & OS.ES_MULTILINE) != 0) {
2975                                 Control control = findBackgroundControl ();
2976                                 if (control == null && background == -1) {
2977                                         if ((state & THEME_BACKGROUND) != 0) {
2978                                                 if (OS.IsAppThemed ()) {
2979                                                         control = findThemeControl ();
2980                                                         if (control != null) {
2981                                                                 OS.SetTextColor (wParam, getForegroundPixel ());
2982                                                                 OS.SetBkColor (wParam, getBackgroundPixel ());
2983                                                                 OS.SetBkMode (wParam, OS.TRANSPARENT);
2984                                                                 return new LRESULT (OS.GetStockObject (OS.NULL_BRUSH));
2985                                                         }
2986                                                 }
2987                                         }
2988                                 }
2989                         }
2990                 }
2991         }
2992         return super.wmColorChild (wParam, lParam);
2993 }
2994
2995 @Override
2996 LRESULT wmCommandChild (long wParam, long lParam) {
2997         int code = OS.HIWORD (wParam);
2998         switch (code) {
2999                 case OS.EN_CHANGE:
3000                         if (findImageControl () != null) {
3001                                 OS.InvalidateRect (handle, null, true);
3002                         }
3003                         if ((style & SWT.SEARCH) != 0 && hwndCancel != 0) {
3004                                 OS.ShowWindow (hwndCancel, OS.GetWindowTextLength (handle) != 0 ? OS.SW_SHOW : OS.SW_HIDE);
3005                         }
3006                         if (ignoreModify) break;
3007                         /*
3008                         * It is possible (but unlikely), that application
3009                         * code could have disposed the widget in the modify
3010                         * event.  If this happens, end the processing of the
3011                         * Windows message by returning zero as the result of
3012                         * the window proc.
3013                         */
3014                         sendEvent (SWT.Modify);
3015                         if (isDisposed ()) return LRESULT.ZERO;
3016                         break;
3017                 case OS.EN_ALIGN_LTR_EC:
3018                 case OS.EN_ALIGN_RTL_EC:
3019                         /*
3020                          * Ctrl + Shift to set explicit LTR or RTL text direction was
3021                          * pressed, so auto direction should no longer be effective.
3022                          */
3023                         state &= ~HAS_AUTO_DIRECTION;
3024                         int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
3025                         if ((bits & OS.WS_EX_RTLREADING) != 0) {
3026                                 style &= ~SWT.LEFT_TO_RIGHT;
3027                                 style |= SWT.RIGHT_TO_LEFT;
3028                         } else {
3029                                 style &= ~SWT.RIGHT_TO_LEFT;
3030                                 style |= SWT.LEFT_TO_RIGHT;
3031                         }
3032                         Event event = new Event();
3033                         event.doit = true;
3034                         sendEvent(SWT.OrientationChange, event);
3035                         if (!event.doit) {
3036                                 if (code == OS.EN_ALIGN_LTR_EC) {
3037                                         bits |= (OS.WS_EX_RTLREADING | OS.WS_EX_LEFTSCROLLBAR);
3038                                         style &= ~SWT.LEFT_TO_RIGHT;
3039                                         style |= SWT.RIGHT_TO_LEFT;
3040                                 } else {
3041                                         bits &= ~(OS.WS_EX_RTLREADING | OS.WS_EX_LEFTSCROLLBAR);
3042                                         style &= ~SWT.RIGHT_TO_LEFT;
3043                                         style |= SWT.LEFT_TO_RIGHT;
3044                                 }
3045                                 OS.SetWindowLong (handle, OS.GWL_EXSTYLE, bits);
3046                         } else {
3047                                 clearSegments (true);
3048                                 applySegments ();
3049                         }
3050                         fixAlignment();
3051                         break;
3052         }
3053         return super.wmCommandChild (wParam, lParam);
3054 }
3055
3056 @Override
3057 LRESULT wmKeyDown (long hwnd, long wParam, long lParam) {
3058         LRESULT result = super.wmKeyDown (hwnd, wParam, lParam);
3059         if (result != null) return result;
3060
3061         if (segments != null) {
3062                 switch ((int)wParam) {
3063                 case OS.VK_LEFT:
3064                 case OS.VK_UP:
3065                 case OS.VK_RIGHT:
3066                 case OS.VK_DOWN:
3067                         long code = 0;
3068                         int [] start = new int [1], end = new int [1], newStart = new int [1], newEnd = new int [1];
3069                         OS.SendMessage (handle, OS.EM_GETSEL, start, end);
3070                         while (true) {
3071                                 code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam);
3072                                 OS.SendMessage (handle, OS.EM_GETSEL, newStart, newEnd);
3073                                 if (newStart [0] != start [0]) {
3074                                         if (untranslateOffset (newStart [0]) != untranslateOffset (start [0])) break;
3075                                 } else if (newEnd [0] != end [0]) {
3076                                         if (untranslateOffset (newEnd [0]) != untranslateOffset (end [0]))  break;
3077                                 } else {
3078                                         break;
3079                                 }
3080                                 start [0] = newStart [0];
3081                                 end [0] = newEnd [0];
3082                         }
3083                         result = code == 0 ? LRESULT.ZERO : new LRESULT (code);
3084                 }
3085         }
3086         return result;
3087 }
3088
3089 }