]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Spinner.java
Remove invalid SHA-256-Digests
[simantics/platform.git] / bundles / org.eclipse.swt.win32.win32.x86_64 / src / org / eclipse / swt / widgets / Spinner.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2012 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 org.eclipse.swt.*;
18 import org.eclipse.swt.events.*;
19 import org.eclipse.swt.graphics.*;
20 import org.eclipse.swt.internal.win32.*;
21
22 /**
23  * Instances of this class are selectable user interface
24  * objects that allow the user to enter and modify numeric
25  * values.
26  * <p>
27  * Note that although this class is a subclass of <code>Composite</code>,
28  * it does not make sense to add children to it, or set a layout on it.
29  * </p>
30  * <dl>
31  * <dt><b>Styles:</b></dt>
32  * <dd>READ_ONLY, WRAP</dd>
33  * <dt><b>Events:</b></dt>
34  * <dd>Selection, Modify, Verify</dd>
35  * </dl>
36  * <p>
37  * IMPORTANT: This class is <em>not</em> intended to be subclassed.
38  * </p>
39  *
40  * @see <a href="http://www.eclipse.org/swt/snippets/#spinner">Spinner snippets</a>
41  * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
42  * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
43  *
44  * @since 3.1
45  * @noextend This class is not intended to be subclassed by clients.
46  */
47 public class Spinner extends Composite {
48         long hwndText, hwndUpDown;
49         boolean ignoreModify, ignoreCharacter;
50         int pageIncrement, digits;
51         static final long EditProc;
52         static final TCHAR EditClass = new TCHAR (0, "EDIT", true);
53         static final long UpDownProc;
54         static final TCHAR UpDownClass = new TCHAR (0, OS.UPDOWN_CLASS, true);
55         static {
56                 WNDCLASS lpWndClass = new WNDCLASS ();
57                 OS.GetClassInfo (0, EditClass, lpWndClass);
58                 EditProc = lpWndClass.lpfnWndProc;
59                 OS.GetClassInfo (0, UpDownClass, lpWndClass);
60                 UpDownProc = lpWndClass.lpfnWndProc;
61         }
62
63         /**
64          * the operating system limit for the number of characters
65          * that the text field in an instance of this class can hold
66          *
67          * @since 3.4
68          */
69         public static final int LIMIT;
70
71         /*
72          * These values can be different on different platforms.
73          * Therefore they are not initialized in the declaration
74          * to stop the compiler from inlining.
75          */
76         static {
77                 LIMIT = 0x7FFFFFFF;
78         }
79
80 /**
81  * Constructs a new instance of this class given its parent
82  * and a style value describing its behavior and appearance.
83  * <p>
84  * The style value is either one of the style constants defined in
85  * class <code>SWT</code> which is applicable to instances of this
86  * class, or must be built by <em>bitwise OR</em>'ing together
87  * (that is, using the <code>int</code> "|" operator) two or more
88  * of those <code>SWT</code> style constants. The class description
89  * lists the style constants that are applicable to the class.
90  * Style bits are also inherited from superclasses.
91  * </p>
92  *
93  * @param parent a composite control which will be the parent of the new instance (cannot be null)
94  * @param style the style of control to construct
95  *
96  * @exception IllegalArgumentException <ul>
97  *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
98  * </ul>
99  * @exception SWTException <ul>
100  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
101  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
102  * </ul>
103  *
104  * @see SWT#READ_ONLY
105  * @see SWT#WRAP
106  * @see Widget#checkSubclass
107  * @see Widget#getStyle
108  */
109 public Spinner (Composite parent, int style) {
110         super (parent, checkStyle (style));
111 }
112
113 @Override
114 long callWindowProc (long hwnd, int msg, long wParam, long lParam) {
115         if (handle == 0) return 0;
116         if (hwnd == hwndText) {
117                 return OS.CallWindowProc (EditProc, hwnd, msg, wParam, lParam);
118         }
119         if (hwnd == hwndUpDown) {
120                 return OS.CallWindowProc (UpDownProc, hwnd, msg, wParam, lParam);
121         }
122         return OS.DefWindowProc (handle, msg, wParam, lParam);
123 }
124
125 static int checkStyle (int style) {
126         /*
127         * Even though it is legal to create this widget
128         * with scroll bars, they serve no useful purpose
129         * because they do not automatically scroll the
130         * widget's client area.  The fix is to clear
131         * the SWT style.
132         */
133         return style & ~(SWT.H_SCROLL | SWT.V_SCROLL);
134 }
135
136 @Override
137 boolean checkHandle (long hwnd) {
138         return hwnd == handle || hwnd == hwndText || hwnd == hwndUpDown;
139 }
140
141 @Override
142 protected void checkSubclass () {
143         if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
144 }
145
146 @Override
147 void createHandle () {
148         super.createHandle ();
149         state &= ~(CANVAS | THEME_BACKGROUND);
150         long hInstance = OS.GetModuleHandle (null);
151         int textExStyle = (style & SWT.BORDER) != 0 ? OS.WS_EX_CLIENTEDGE : 0;
152         int textStyle = OS.WS_CHILD | OS.WS_VISIBLE | OS.ES_AUTOHSCROLL | OS.WS_CLIPSIBLINGS;
153         if ((style & SWT.READ_ONLY) != 0) textStyle |= OS.ES_READONLY;
154         if ((style & SWT.RIGHT_TO_LEFT) != 0) textExStyle |= OS.WS_EX_LAYOUTRTL;
155         hwndText = OS.CreateWindowEx (
156                 textExStyle,
157                 EditClass,
158                 null,
159                 textStyle,
160                 0, 0, 0, 0,
161                 handle,
162                 0,
163                 hInstance,
164                 null);
165         if (hwndText == 0) error (SWT.ERROR_NO_HANDLES);
166         OS.SetWindowLongPtr (hwndText, OS.GWLP_ID, hwndText);
167         int upDownStyle = OS.WS_CHILD | OS.WS_VISIBLE | OS.UDS_AUTOBUDDY;
168         if ((style & SWT.WRAP) != 0) upDownStyle |= OS.UDS_WRAP;
169         if ((style & SWT.BORDER) != 0) {
170                 if ((style & SWT.RIGHT_TO_LEFT) != 0) {
171                         upDownStyle |= OS.UDS_ALIGNLEFT;
172                 } else {
173                         upDownStyle |= OS.UDS_ALIGNRIGHT;
174                 }
175         }
176         hwndUpDown = OS.CreateWindowEx (
177                 0,
178                 UpDownClass,
179                 null,
180                 upDownStyle,
181                 0, 0, 0, 0,
182                 handle,
183                 0,
184                 hInstance,
185                 null);
186         if (hwndUpDown == 0) error (SWT.ERROR_NO_HANDLES);
187         int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE;
188         OS.SetWindowPos (hwndText, hwndUpDown, 0, 0, 0, 0, flags);
189         OS.SetWindowLongPtr (hwndUpDown, OS.GWLP_ID, hwndUpDown);
190         if (OS.IsDBLocale) {
191                 long hIMC = OS.ImmGetContext (handle);
192                 OS.ImmAssociateContext (hwndText, hIMC);
193                 OS.ImmAssociateContext (hwndUpDown, hIMC);
194                 OS.ImmReleaseContext (handle, hIMC);
195         }
196         OS.SendMessage (hwndUpDown, OS.UDM_SETRANGE32, 0, 100);
197         OS.SendMessage (hwndUpDown, OS.UDM_SETPOS32, 0, 0);
198         pageIncrement = 10;
199         digits = 0;
200         OS.SetWindowText (hwndText, new char [] {'0', '\0'});
201 }
202
203 /**
204  * Adds the listener to the collection of listeners who will
205  * be notified when the receiver's text is modified, by sending
206  * it one of the messages defined in the <code>ModifyListener</code>
207  * interface.
208  *
209  * @param listener the listener which should be notified
210  *
211  * @exception IllegalArgumentException <ul>
212  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
213  * </ul>
214  * @exception SWTException <ul>
215  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
216  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
217  * </ul>
218  *
219  * @see ModifyListener
220  * @see #removeModifyListener
221  */
222 public void addModifyListener (ModifyListener listener) {
223         checkWidget ();
224         if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
225         TypedListener typedListener = new TypedListener (listener);
226         addListener (SWT.Modify, typedListener);
227 }
228
229 /**
230  * Adds the listener to the collection of listeners who will
231  * be notified when the control is selected by the user, by sending
232  * it one of the messages defined in the <code>SelectionListener</code>
233  * interface.
234  * <p>
235  * <code>widgetSelected</code> is not called for texts.
236  * <code>widgetDefaultSelected</code> is typically called when ENTER is pressed in a single-line text.
237  * </p>
238  *
239  * @param listener the listener which should be notified when the control is selected by the user
240  *
241  * @exception IllegalArgumentException <ul>
242  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
243  * </ul>
244  * @exception SWTException <ul>
245  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
246  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
247  * </ul>
248  *
249  * @see SelectionListener
250  * @see #removeSelectionListener
251  * @see SelectionEvent
252  */
253 public void addSelectionListener(SelectionListener listener) {
254         checkWidget ();
255         if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
256         TypedListener typedListener = new TypedListener (listener);
257         addListener (SWT.Selection,typedListener);
258         addListener (SWT.DefaultSelection,typedListener);
259 }
260
261 /**
262  * Adds the listener to the collection of listeners who will
263  * be notified when the receiver's text is verified, by sending
264  * it one of the messages defined in the <code>VerifyListener</code>
265  * interface.
266  *
267  * @param listener the listener which should be notified
268  *
269  * @exception IllegalArgumentException <ul>
270  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
271  * </ul>
272  * @exception SWTException <ul>
273  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
274  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
275  * </ul>
276  *
277  * @see VerifyListener
278  * @see #removeVerifyListener
279  */
280 void addVerifyListener (VerifyListener listener) {
281         checkWidget();
282         if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
283         TypedListener typedListener = new TypedListener (listener);
284         addListener (SWT.Verify, typedListener);
285 }
286
287 @Override
288 long borderHandle () {
289         return hwndText;
290 }
291
292 @Override Point computeSizeInPixels (int wHint, int hHint, boolean changed) {
293         checkWidget ();
294         int width = 0, height = 0;
295         if (wHint == SWT.DEFAULT || hHint == SWT.DEFAULT) {
296                 long newFont, oldFont = 0;
297                 long hDC = OS.GetDC (hwndText);
298                 newFont = OS.SendMessage (hwndText, OS.WM_GETFONT, 0, 0);
299                 if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
300                 TEXTMETRIC tm = new TEXTMETRIC ();
301                 OS.GetTextMetrics (hDC, tm);
302                 height = tm.tmHeight;
303                 RECT rect = new RECT ();
304                 int [] max = new int [1];
305                 OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, null, max);
306                 String string = String.valueOf (max [0]);
307                 if (digits > 0) {
308                         StringBuilder buffer = new StringBuilder ();
309                         buffer.append (string);
310                         buffer.append (getDecimalSeparator ());
311                         int count = digits - string.length ();
312                         while (count >= 0) {
313                                 buffer.append ("0");
314                                 count--;
315                         }
316                         string = buffer.toString ();
317                 }
318                 char [] buffer = string.toCharArray ();
319                 int flags = OS.DT_CALCRECT | OS.DT_EDITCONTROL | OS.DT_NOPREFIX;
320                 OS.DrawText (hDC, buffer, buffer.length, rect, flags);
321                 width = rect.right - rect.left;
322                 if (newFont != 0) OS.SelectObject (hDC, oldFont);
323                 OS.ReleaseDC (hwndText, hDC);
324         }
325         if (width == 0) width = DEFAULT_WIDTH;
326         if (height == 0) height = DEFAULT_HEIGHT;
327         if (wHint != SWT.DEFAULT) width = wHint;
328         if (hHint != SWT.DEFAULT) height = hHint;
329         Rectangle trim = computeTrimInPixels (0, 0, width, height);
330         if (hHint == SWT.DEFAULT) {
331                 int upDownHeight = OS.GetSystemMetrics (OS.SM_CYVSCROLL) + 2 * getBorderWidthInPixels ();
332                 upDownHeight += (style & SWT.BORDER) != 0 ? 1 : 3;
333                 trim.height = Math.max (trim.height, upDownHeight);
334         }
335         return new Point (trim.width, trim.height);
336 }
337
338 @Override Rectangle computeTrimInPixels (int x, int y, int width, int height) {
339         checkWidget ();
340
341         /* Get the trim of the text control */
342         RECT rect = new RECT ();
343         OS.SetRect (rect, x, y, x + width, y + height);
344         int bits0 = OS.GetWindowLong (hwndText, OS.GWL_STYLE);
345         int bits1 = OS.GetWindowLong (hwndText, OS.GWL_EXSTYLE);
346         OS.AdjustWindowRectEx (rect, bits0, false, bits1);
347         width = rect.right - rect.left;
348         height = rect.bottom - rect.top;
349
350         /*
351         * The preferred height of a single-line text widget
352         * has been hand-crafted to be the same height as
353         * the single-line text widget in an editable combo
354         * box.
355         */
356         long margins = OS.SendMessage (hwndText, OS.EM_GETMARGINS, 0, 0);
357         x -= OS.LOWORD (margins);
358         width += OS.LOWORD (margins) + OS.HIWORD (margins);
359         if ((style & SWT.BORDER) != 0) {
360                 x -= 1;
361                 y -= 1;
362                 width += 2;
363                 height += 2;
364         }
365         width += OS.GetSystemMetrics (OS.SM_CXVSCROLL);
366         return new Rectangle (x, y, width, height);
367 }
368
369 /**
370  * Copies the selected text.
371  * <p>
372  * The current selection is copied to the clipboard.
373  * </p>
374  *
375  * @exception SWTException <ul>
376  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
377  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
378  * </ul>
379  */
380 public void copy () {
381         checkWidget ();
382         OS.SendMessage (hwndText, OS.WM_COPY, 0, 0);
383 }
384
385 /**
386  * Cuts the selected text.
387  * <p>
388  * The current selection is first copied to the
389  * clipboard and then deleted from the widget.
390  * </p>
391  *
392  * @exception SWTException <ul>
393  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
394  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
395  * </ul>
396  */
397 public void cut () {
398         checkWidget ();
399         if ((style & SWT.READ_ONLY) != 0) return;
400         OS.SendMessage (hwndText, OS.WM_CUT, 0, 0);
401 }
402
403 @Override
404 int defaultBackground () {
405         return OS.GetSysColor (OS.COLOR_WINDOW);
406 }
407
408 @Override
409 void enableWidget (boolean enabled) {
410         super.enableWidget (enabled);
411         OS.EnableWindow (hwndText, enabled);
412         OS.EnableWindow (hwndUpDown, enabled);
413 }
414
415 @Override
416 void deregister () {
417         super.deregister ();
418         display.removeControl (hwndText);
419         display.removeControl (hwndUpDown);
420 }
421
422 @Override
423 boolean hasFocus () {
424         long hwndFocus = OS.GetFocus ();
425         if (hwndFocus == handle) return true;
426         if (hwndFocus == hwndText) return true;
427         if (hwndFocus == hwndUpDown) return true;
428         return false;
429 }
430
431 /**
432  * Returns the number of decimal places used by the receiver.
433  *
434  * @return the digits
435  *
436  * @exception SWTException <ul>
437  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
438  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
439  * </ul>
440  */
441 public int getDigits () {
442         checkWidget ();
443         return digits;
444 }
445
446 String getDecimalSeparator () {
447         char [] data = new char [4];
448         int size = OS.GetLocaleInfo (OS.LOCALE_USER_DEFAULT, OS.LOCALE_SDECIMAL, data, 4);
449         return size != 0 ? new String (data, 0, size - 1) : ".";
450 }
451
452 /**
453  * Returns the amount that the receiver's value will be
454  * modified by when the up/down arrows are pressed.
455  *
456  * @return the increment
457  *
458  * @exception SWTException <ul>
459  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
460  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
461  * </ul>
462  */
463 public int getIncrement () {
464         checkWidget ();
465         UDACCEL udaccel = new UDACCEL ();
466         OS.SendMessage (hwndUpDown, OS.UDM_GETACCEL, 1, udaccel);
467         return udaccel.nInc;
468 }
469
470 /**
471  * Returns the maximum value which the receiver will allow.
472  *
473  * @return the maximum
474  *
475  * @exception SWTException <ul>
476  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
477  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
478  * </ul>
479  */
480 public int getMaximum () {
481         checkWidget ();
482         int [] max = new int [1];
483         OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, null, max);
484         return max [0];
485 }
486
487 /**
488  * Returns the minimum value which the receiver will allow.
489  *
490  * @return the minimum
491  *
492  * @exception SWTException <ul>
493  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
494  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
495  * </ul>
496  */
497 public int getMinimum () {
498         checkWidget ();
499         int [] min = new int [1];
500         OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, min, null);
501         return min [0];
502 }
503
504 /**
505  * Returns the amount that the receiver's position will be
506  * modified by when the page up/down keys are pressed.
507  *
508  * @return the page increment
509  *
510  * @exception SWTException <ul>
511  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
512  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
513  * </ul>
514  */
515 public int getPageIncrement () {
516         checkWidget ();
517         return pageIncrement;
518 }
519
520 /**
521  * Returns the <em>selection</em>, which is the receiver's position.
522  *
523  * @return the selection
524  *
525  * @exception SWTException <ul>
526  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
527  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
528  * </ul>
529  */
530 public int getSelection () {
531         checkWidget ();
532         return (int)OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0);
533 }
534
535 int getSelectionText (boolean [] parseFail) {
536         int length = OS.GetWindowTextLength (hwndText);
537         char [] buffer = new char [length + 1];
538         OS.GetWindowText (hwndText, buffer, length + 1);
539         String string = new String (buffer, 0, length);
540         try {
541                 int value;
542                 if (digits > 0) {
543                         String decimalSeparator = getDecimalSeparator ();
544                         int index = string.indexOf (decimalSeparator);
545                         if (index != -1)  {
546                                 int startIndex = string.startsWith ("+") || string.startsWith ("-") ? 1 : 0;
547                                 String wholePart = startIndex != index ? string.substring (startIndex, index) : "0";
548                                 String decimalPart = string.substring (index + 1);
549                                 if (decimalPart.length () > digits) {
550                                         decimalPart = decimalPart.substring (0, digits);
551                                 } else {
552                                         int i = digits - decimalPart.length ();
553                                         for (int j = 0; j < i; j++) {
554                                                 decimalPart = decimalPart + "0";
555                                         }
556                                 }
557                                 int wholeValue = Integer.parseInt (wholePart);
558                                 int decimalValue = Integer.parseInt (decimalPart);
559                                 for (int i = 0; i < digits; i++) wholeValue *= 10;
560                                 value = wholeValue + decimalValue;
561                                 if (string.startsWith ("-")) value = -value;
562                         } else {
563                                 value = Integer.parseInt (string);
564                                 for (int i = 0; i < digits; i++) value *= 10;
565                         }
566                 } else {
567                         value = Integer.parseInt (string);
568                 }
569                 int [] max = new int [1], min = new int [1];
570                 OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, min, max);
571                 if (min [0] <= value && value <= max [0]) return value;
572         } catch (NumberFormatException e) {
573         }
574         parseFail [0] = true;
575         return -1;
576 }
577
578 /**
579  * Returns a string containing a copy of the contents of the
580  * receiver's text field, or an empty string if there are no
581  * contents.
582  *
583  * @return the receiver's text
584  *
585  * @exception SWTException <ul>
586  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
587  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
588  * </ul>
589  *
590  * @since 3.4
591  */
592 public String getText () {
593         checkWidget ();
594         int length = OS.GetWindowTextLength (hwndText);
595         if (length == 0) return "";
596         char [] buffer = new char [length + 1];
597         OS.GetWindowText (hwndText, buffer, length + 1);
598         return new String (buffer, 0, length);
599 }
600
601 /**
602  * Returns the maximum number of characters that the receiver's
603  * text field is capable of holding. If this has not been changed
604  * by <code>setTextLimit()</code>, it will be the constant
605  * <code>Spinner.LIMIT</code>.
606  *
607  * @return the text limit
608  *
609  * @exception SWTException <ul>
610  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
611  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
612  * </ul>
613  *
614  * @see #LIMIT
615  *
616  * @since 3.4
617  */
618 public int getTextLimit () {
619         checkWidget ();
620         return (int)OS.SendMessage (hwndText, OS.EM_GETLIMITTEXT, 0, 0) & 0x7FFFFFFF;
621 }
622
623 /**
624  * Pastes text from clipboard.
625  * <p>
626  * The selected text is deleted from the widget
627  * and new text inserted from the clipboard.
628  * </p>
629  *
630  * @exception SWTException <ul>
631  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
632  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
633  * </ul>
634  */
635 public void paste () {
636         checkWidget ();
637         if ((style & SWT.READ_ONLY) != 0) return;
638         OS.SendMessage (hwndText, OS.WM_PASTE, 0, 0);
639 }
640
641 @Override
642 void register () {
643         super.register ();
644         display.addControl (hwndText, this);
645         display.addControl (hwndUpDown, this);
646 }
647
648 @Override
649 void releaseHandle () {
650         super.releaseHandle ();
651         hwndText = hwndUpDown = 0;
652 }
653
654 /**
655  * Removes the listener from the collection of listeners who will
656  * be notified when the receiver's text is modified.
657  *
658  * @param listener the listener which should no longer be notified
659  *
660  * @exception IllegalArgumentException <ul>
661  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
662  * </ul>
663  * @exception SWTException <ul>
664  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
665  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
666  * </ul>
667  *
668  * @see ModifyListener
669  * @see #addModifyListener
670  */
671 public void removeModifyListener (ModifyListener listener) {
672         checkWidget ();
673         if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
674         if (eventTable == null) return;
675         eventTable.unhook (SWT.Modify, listener);
676 }
677
678 /**
679  * Removes the listener from the collection of listeners who will
680  * be notified when the control is selected by the user.
681  *
682  * @param listener the listener which should no longer be notified
683  *
684  * @exception IllegalArgumentException <ul>
685  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
686  * </ul>
687  * @exception SWTException <ul>
688  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
689  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
690  * </ul>
691  *
692  * @see SelectionListener
693  * @see #addSelectionListener
694  */
695 public void removeSelectionListener(SelectionListener listener) {
696         checkWidget ();
697         if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
698         if (eventTable == null) return;
699         eventTable.unhook (SWT.Selection, listener);
700         eventTable.unhook (SWT.DefaultSelection,listener);
701 }
702
703 /**
704  * Removes the listener from the collection of listeners who will
705  * be notified when the control is verified.
706  *
707  * @param listener the listener which should no longer be notified
708  *
709  * @exception IllegalArgumentException <ul>
710  *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
711  * </ul>
712  * @exception SWTException <ul>
713  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
714  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
715  * </ul>
716  *
717  * @see VerifyListener
718  * @see #addVerifyListener
719  */
720 void removeVerifyListener (VerifyListener listener) {
721         checkWidget ();
722         if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
723         if (eventTable == null) return;
724         eventTable.unhook (SWT.Verify, listener);
725 }
726
727 @Override
728 boolean sendKeyEvent (int type, int msg, long wParam, long lParam, Event event) {
729         if (!super.sendKeyEvent (type, msg, wParam, lParam, event)) {
730                 return false;
731         }
732         if ((style & SWT.READ_ONLY) != 0) return true;
733         if (type != SWT.KeyDown) return true;
734         if (msg != OS.WM_CHAR && msg != OS.WM_KEYDOWN && msg != OS.WM_IME_CHAR) {
735                 return true;
736         }
737         if (event.character == 0) return true;
738 //      if (!hooks (SWT.Verify) && !filters (SWT.Verify)) return true;
739         char key = event.character;
740         int stateMask = event.stateMask;
741
742         /*
743         * Disable all magic keys that could modify the text
744         * and don't send events when Alt, Shift or Ctrl is
745         * pressed.
746         */
747         switch (msg) {
748                 case OS.WM_CHAR:
749                         if (key != 0x08 && key != 0x7F && key != '\r' && key != '\t' && key != '\n') break;
750                         // FALL THROUGH
751                 case OS.WM_KEYDOWN:
752                         if ((stateMask & (SWT.ALT | SWT.SHIFT | SWT.CONTROL)) != 0) return false;
753                         break;
754         }
755
756         /*
757         * If the left button is down, the text widget refuses the character.
758         */
759         if (OS.GetKeyState (OS.VK_LBUTTON) < 0) {
760                 return true;
761         }
762
763         /* Verify the character */
764         String oldText = "";
765         int [] start = new int [1], end = new int [1];
766         OS.SendMessage (hwndText, OS.EM_GETSEL, start, end);
767         switch (key) {
768                 case 0x08:      /* Bs */
769                         if (start [0] == end [0]) {
770                                 if (start [0] == 0) return true;
771                                 start [0] = start [0] - 1;
772                                 start [0] = Math.max (start [0], 0);
773                         }
774                         break;
775                 case 0x7F:      /* Del */
776                         if (start [0] == end [0]) {
777                                 int length = OS.GetWindowTextLength (hwndText);
778                                 if (start [0] == length) return true;
779                                 end [0] = end [0] + 1;
780                                 end [0] = Math.min (end [0], length);
781                         }
782                         break;
783                 case '\r':      /* Return */
784                         return true;
785                 default:        /* Tab and other characters */
786                         if (key != '\t' && key < 0x20) return true;
787                         oldText = new String (new char [] {key});
788                         break;
789         }
790         String newText = verifyText (oldText, start [0], end [0], event);
791         if (newText == null) return false;
792         if (newText == oldText) return true;
793         TCHAR buffer = new TCHAR (getCodePage (), newText, true);
794         OS.SendMessage (hwndText, OS.EM_SETSEL, start [0], end [0]);
795         OS.SendMessage (hwndText, OS.EM_REPLACESEL, 0, buffer);
796         return false;
797 }
798
799 @Override
800 void setBackgroundImage (long hBitmap) {
801         super.setBackgroundImage (hBitmap);
802         OS.InvalidateRect (hwndText, null, true);
803 }
804
805 @Override
806 void setBackgroundPixel (int pixel) {
807         super.setBackgroundPixel (pixel);
808         OS.InvalidateRect (hwndText, null, true);
809 }
810
811 /**
812  * Sets the number of decimal places used by the receiver.
813  * <p>
814  * The digit setting is used to allow for floating point values in the receiver.
815  * For example, to set the selection to a floating point value of 1.37 call setDigits() with
816  * a value of 2 and setSelection() with a value of 137. Similarly, if getDigits() has a value
817  * of 2 and getSelection() returns 137 this should be interpreted as 1.37. This applies to all
818  * numeric APIs.
819  * </p>
820  *
821  * @param value the new digits (must be greater than or equal to zero)
822  *
823  * @exception IllegalArgumentException <ul>
824  *    <li>ERROR_INVALID_ARGUMENT - if the value is less than zero</li>
825  * </ul>
826  * @exception SWTException <ul>
827  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
828  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
829  * </ul>
830  */
831 public void setDigits (int value) {
832         checkWidget ();
833         if (value < 0) error (SWT.ERROR_INVALID_ARGUMENT);
834         if (value == this.digits) return;
835         this.digits = value;
836         int pos = (int)OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0);
837         setSelection (pos, false, true, false);
838 }
839
840 @Override
841 void setForegroundPixel (int pixel) {
842         super.setForegroundPixel (pixel);
843         OS.InvalidateRect (hwndText, null, true);
844 }
845
846 /**
847  * Sets the amount that the receiver's value will be
848  * modified by when the up/down arrows are pressed to
849  * the argument, which must be at least one.
850  *
851  * @param value the new increment (must be greater than zero)
852  *
853  * @exception SWTException <ul>
854  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
855  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
856  * </ul>
857  */
858 public void setIncrement (int value) {
859         checkWidget ();
860         if (value < 1) return;
861         long hHeap = OS.GetProcessHeap ();
862         int count = (int)OS.SendMessage (hwndUpDown, OS.UDM_GETACCEL, 0, (UDACCEL)null);
863         long udaccels = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, UDACCEL.sizeof * count);
864         OS.SendMessage (hwndUpDown, OS.UDM_GETACCEL, count, udaccels);
865         int first = -1;
866         UDACCEL udaccel = new UDACCEL ();
867         for (int i = 0; i < count; i++) {
868                 long offset = udaccels + (i * UDACCEL.sizeof);
869                 OS.MoveMemory (udaccel, offset, UDACCEL.sizeof);
870                 if (first == -1) first = udaccel.nInc;
871                 udaccel.nInc  = udaccel.nInc / first * value;
872                 OS.MoveMemory (offset, udaccel, UDACCEL.sizeof);
873         }
874         OS.SendMessage (hwndUpDown, OS.UDM_SETACCEL, count, udaccels);
875         OS.HeapFree (hHeap, 0, udaccels);
876 }
877
878 /**
879  * Sets the maximum value that the receiver will allow.  This new
880  * value will be ignored if it is less than the receiver's current
881  * minimum value.  If the new maximum is applied then the receiver's
882  * selection value will be adjusted if necessary to fall within its new range.
883  *
884  * @param value the new maximum, which must be greater than or equal to the current minimum
885  *
886  * @exception SWTException <ul>
887  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
888  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
889  * </ul>
890  */
891 public void setMaximum (int value) {
892         checkWidget ();
893         int [] min = new int [1];
894         OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, min, null);
895         if (value < min [0]) return;
896         int pos = (int)OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0);
897         OS.SendMessage (hwndUpDown , OS.UDM_SETRANGE32, min [0], value);
898         if (pos > value) setSelection (value, true, true, false);
899 }
900
901 /**
902  * Sets the minimum value that the receiver will allow.  This new
903  * value will be ignored if it is greater than the receiver's
904  * current maximum value.  If the new minimum is applied then the receiver's
905  * selection value will be adjusted if necessary to fall within its new range.
906  *
907  * @param value the new minimum, which must be less than or equal to the current maximum
908  *
909  * @exception SWTException <ul>
910  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
911  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
912  * </ul>
913  */
914 public void setMinimum (int value) {
915         checkWidget ();
916         int [] max = new int [1];
917         OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, null, max);
918         if (value > max [0]) return;
919         int pos = (int)OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0);
920         OS.SendMessage (hwndUpDown , OS.UDM_SETRANGE32, value, max [0]);
921         if (pos < value) setSelection (value, true, true, false);
922 }
923
924 /**
925  * Sets the amount that the receiver's position will be
926  * modified by when the page up/down keys are pressed
927  * to the argument, which must be at least one.
928  *
929  * @param value the page increment (must be greater than zero)
930  *
931  * @exception SWTException <ul>
932  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
933  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
934  * </ul>
935  */
936 public void setPageIncrement (int value) {
937         checkWidget ();
938         if (value < 1) return;
939         pageIncrement = value;
940 }
941
942 /**
943  * Sets the <em>selection</em>, which is the receiver's
944  * position, to the argument. If the argument is not within
945  * the range specified by minimum and maximum, it will be
946  * adjusted to fall within this range.
947  *
948  * @param value the new selection (must be zero or greater)
949  *
950  * @exception SWTException <ul>
951  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
952  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
953  * </ul>
954  */
955 public void setSelection (int value) {
956         checkWidget ();
957         int [] max = new int [1], min = new int [1];
958         OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, min, max);
959         value = Math.min (Math.max (min [0], value), max [0]);
960         setSelection (value, true, true, false);
961 }
962
963 void setSelection (int value, boolean setPos, boolean setText, boolean notify) {
964         if (setPos) {
965                 OS.SendMessage (hwndUpDown, OS.UDM_SETPOS32, 0, value);
966         }
967         if (setText) {
968                 String string;
969                 if (digits == 0) {
970                         string = String.valueOf (value);
971                 } else {
972                         string = String.valueOf (Math.abs (value));
973                         String decimalSeparator = getDecimalSeparator ();
974                         int index = string.length () - digits;
975                         StringBuilder buffer = new StringBuilder ();
976                         if (value < 0) buffer.append ("-");
977                         if (index > 0) {
978                                 buffer.append (string.substring (0, index));
979                                 buffer.append (decimalSeparator);
980                                 buffer.append (string.substring (index));
981                         } else {
982                                 buffer.append ("0");
983                                 buffer.append (decimalSeparator);
984                                 while (index++ < 0) buffer.append ("0");
985                                 buffer.append (string);
986                         }
987                         string = buffer.toString ();
988                 }
989                 if (hooks (SWT.Verify) || filters (SWT.Verify)) {
990                         int length = OS.GetWindowTextLength (hwndText);
991                         string = verifyText (string, 0, length, null);
992                         if (string == null) return;
993                 }
994                 TCHAR buffer = new TCHAR (getCodePage (), string, true);
995                 OS.SetWindowText (hwndText, buffer);
996                 OS.SendMessage (hwndText, OS.EM_SETSEL, 0, -1);
997                 OS.NotifyWinEvent (OS.EVENT_OBJECT_FOCUS, hwndText, OS.OBJID_CLIENT, 0);
998         }
999         if (notify) sendSelectionEvent (SWT.Selection);
1000 }
1001
1002 /**
1003  * Sets the maximum number of characters that the receiver's
1004  * text field is capable of holding to be the argument.
1005  * <p>
1006  * To reset this value to the default, use <code>setTextLimit(Spinner.LIMIT)</code>.
1007  * Specifying a limit value larger than <code>Spinner.LIMIT</code> sets the
1008  * receiver's limit to <code>Spinner.LIMIT</code>.
1009  * </p>
1010  * @param limit new text limit
1011  *
1012  * @exception IllegalArgumentException <ul>
1013  *    <li>ERROR_CANNOT_BE_ZERO - if the limit is zero</li>
1014  * </ul>
1015  * @exception SWTException <ul>
1016  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1017  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1018  * </ul>
1019  *
1020  * @see #LIMIT
1021  *
1022  * @since 3.4
1023  */
1024 public void setTextLimit (int limit) {
1025         checkWidget ();
1026         if (limit == 0) error (SWT.ERROR_CANNOT_BE_ZERO);
1027         OS.SendMessage (hwndText, OS.EM_SETLIMITTEXT, limit, 0);
1028 }
1029
1030 @Override
1031 void setToolTipText (Shell shell, String string) {
1032         shell.setToolTipText (hwndText, string);
1033         shell.setToolTipText (hwndUpDown, string);
1034 }
1035
1036 /**
1037  * Sets the receiver's selection, minimum value, maximum
1038  * value, digits, increment and page increment all at once.
1039  * <p>
1040  * Note: This is similar to setting the values individually
1041  * using the appropriate methods, but may be implemented in a
1042  * more efficient fashion on some platforms.
1043  * </p>
1044  *
1045  * @param selection the new selection value
1046  * @param minimum the new minimum value
1047  * @param maximum the new maximum value
1048  * @param digits the new digits value
1049  * @param increment the new increment value
1050  * @param pageIncrement the new pageIncrement value
1051  *
1052  * @exception SWTException <ul>
1053  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1054  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1055  * </ul>
1056  *
1057  * @since 3.2
1058  */
1059 public void setValues (int selection, int minimum, int maximum, int digits, int increment, int pageIncrement) {
1060         checkWidget ();
1061         if (maximum < minimum) return;
1062         if (digits < 0) return;
1063         if (increment < 1) return;
1064         if (pageIncrement < 1) return;
1065         selection = Math.min (Math.max (minimum, selection), maximum);
1066         setIncrement (increment);
1067         this.pageIncrement = pageIncrement;
1068         this.digits = digits;
1069         OS.SendMessage (hwndUpDown , OS.UDM_SETRANGE32, minimum, maximum);
1070         setSelection (selection, true, true, false);
1071 }
1072
1073 @Override
1074 void subclass () {
1075         super.subclass ();
1076         long newProc = display.windowProc;
1077         OS.SetWindowLongPtr (hwndText, OS.GWLP_WNDPROC, newProc);
1078         OS.SetWindowLongPtr (hwndUpDown, OS.GWLP_WNDPROC, newProc);
1079 }
1080
1081 @Override
1082 void unsubclass () {
1083         super.unsubclass ();
1084         OS.SetWindowLongPtr (hwndText, OS.GWLP_WNDPROC, EditProc);
1085         OS.SetWindowLongPtr (hwndUpDown, OS.GWLP_WNDPROC, UpDownProc);
1086 }
1087
1088 @Override
1089 void updateOrientation () {
1090         super.updateOrientation ();
1091         int bits  = OS.GetWindowLong (hwndText, OS.GWL_EXSTYLE);
1092         int bits1  = OS.GetWindowLong (hwndText, OS.GWL_STYLE);
1093         if ((style & SWT.RIGHT_TO_LEFT) != 0){
1094                 bits |= OS.WS_EX_RIGHT;
1095                 bits1 |= OS.ES_RIGHT;
1096         }
1097         else{
1098                 bits &= ~OS.WS_EX_RIGHT;
1099                 bits1 &= ~OS.ES_RIGHT;
1100         }
1101         OS.SetWindowLong (hwndText, OS.GWL_STYLE, bits1);
1102         OS.SetWindowLong (hwndText, OS.GWL_EXSTYLE, bits);
1103         RECT rect = new RECT ();
1104         OS.GetWindowRect (handle, rect);
1105         int width = rect.right - rect.left, height = rect.bottom - rect.top;
1106         OS.SetWindowPos (handle, 0, 0, 0, width - 1, height - 1, OS.SWP_NOMOVE | OS.SWP_NOZORDER);
1107         OS.SetWindowPos (handle, 0, 0, 0, width, height, OS.SWP_NOMOVE | OS.SWP_NOZORDER);
1108 }
1109
1110 String verifyText (String string, int start, int end, Event keyEvent) {
1111         Event event = new Event ();
1112         event.text = string;
1113         event.start = start;
1114         event.end = end;
1115         if (keyEvent != null) {
1116                 event.character = keyEvent.character;
1117                 event.keyCode = keyEvent.keyCode;
1118                 event.stateMask = keyEvent.stateMask;
1119         }
1120         int index = 0;
1121         if (digits > 0) {
1122                 String decimalSeparator = getDecimalSeparator ();
1123                 index = string.indexOf (decimalSeparator);
1124                 if (index != -1) {
1125                         string = string.substring (0, index) + string.substring (index + 1);
1126                 }
1127                 index = 0;
1128         }
1129         if (string.length() > 0) {
1130                 int [] min = new int [1];
1131                 OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, min, null);
1132                 if (min [0] < 0 && string.charAt (0) == '-') index++;
1133         }
1134         while (index < string.length ()) {
1135                 if (!Character.isDigit (string.charAt (index))) break;
1136                 index++;
1137         }
1138         event.doit = index == string.length ();
1139         sendEvent (SWT.Verify, event);
1140         if (!event.doit || isDisposed ()) return null;
1141         return event.text;
1142 }
1143
1144 @Override
1145 int widgetExtStyle () {
1146         return super.widgetExtStyle () & ~OS.WS_EX_CLIENTEDGE;
1147 }
1148
1149 @Override
1150 long windowProc (long hwnd, int msg, long wParam, long lParam) {
1151         if (hwnd == hwndText || hwnd == hwndUpDown) {
1152                 LRESULT result = null;
1153                 switch (msg) {
1154                         /* Keyboard messages */
1155                         case OS.WM_CHAR:                result = wmChar (hwnd, wParam, lParam); break;
1156                         case OS.WM_IME_CHAR:    result = wmIMEChar (hwnd, wParam, lParam); break;
1157                         case OS.WM_KEYDOWN:             result = wmKeyDown (hwnd, wParam, lParam); break;
1158                         case OS.WM_KEYUP:               result = wmKeyUp (hwnd, wParam, lParam); break;
1159                         case OS.WM_SYSCHAR:             result = wmSysChar (hwnd, wParam, lParam); break;
1160                         case OS.WM_SYSKEYDOWN:  result = wmSysKeyDown (hwnd, wParam, lParam); break;
1161                         case OS.WM_SYSKEYUP:    result = wmSysKeyUp (hwnd, wParam, lParam); break;
1162
1163                         /* Mouse Messages */
1164                         case OS.WM_CAPTURECHANGED:      result = wmCaptureChanged (hwnd, wParam, lParam); break;
1165                         case OS.WM_LBUTTONDBLCLK:       result = wmLButtonDblClk (hwnd, wParam, lParam); break;
1166                         case OS.WM_LBUTTONDOWN:         result = wmLButtonDown (hwnd, wParam, lParam); break;
1167                         case OS.WM_LBUTTONUP:           result = wmLButtonUp (hwnd, wParam, lParam); break;
1168                         case OS.WM_MBUTTONDBLCLK:       result = wmMButtonDblClk (hwnd, wParam, lParam); break;
1169                         case OS.WM_MBUTTONDOWN:         result = wmMButtonDown (hwnd, wParam, lParam); break;
1170                         case OS.WM_MBUTTONUP:           result = wmMButtonUp (hwnd, wParam, lParam); break;
1171                         case OS.WM_MOUSEHOVER:          result = wmMouseHover (hwnd, wParam, lParam); break;
1172                         case OS.WM_MOUSELEAVE:          result = wmMouseLeave (hwnd, wParam, lParam); break;
1173                         case OS.WM_MOUSEMOVE:           result = wmMouseMove (hwnd, wParam, lParam); break;
1174 //                      case OS.WM_MOUSEWHEEL:          result = wmMouseWheel (hwnd, wParam, lParam); break;
1175                         case OS.WM_RBUTTONDBLCLK:       result = wmRButtonDblClk (hwnd, wParam, lParam); break;
1176                         case OS.WM_RBUTTONDOWN:         result = wmRButtonDown (hwnd, wParam, lParam); break;
1177                         case OS.WM_RBUTTONUP:           result = wmRButtonUp (hwnd, wParam, lParam); break;
1178                         case OS.WM_XBUTTONDBLCLK:       result = wmXButtonDblClk (hwnd, wParam, lParam); break;
1179                         case OS.WM_XBUTTONDOWN:         result = wmXButtonDown (hwnd, wParam, lParam); break;
1180                         case OS.WM_XBUTTONUP:           result = wmXButtonUp (hwnd, wParam, lParam); break;
1181
1182                         /* Focus Messages */
1183                         case OS.WM_SETFOCUS:            result = wmSetFocus (hwnd, wParam, lParam); break;
1184                         case OS.WM_KILLFOCUS:           result = wmKillFocus (hwnd, wParam, lParam); break;
1185
1186                         /* Paint messages */
1187                         case OS.WM_PAINT:                       result = wmPaint (hwnd, wParam, lParam); break;
1188                         case OS.WM_PRINT:                       result = wmPrint (hwnd, wParam, lParam); break;
1189
1190                         /* Menu messages */
1191                         case OS.WM_CONTEXTMENU:         result = wmContextMenu (hwnd, wParam, lParam); break;
1192
1193                         /* Clipboard messages */
1194                         case OS.WM_CLEAR:
1195                         case OS.WM_CUT:
1196                         case OS.WM_PASTE:
1197                         case OS.WM_UNDO:
1198                         case OS.EM_UNDO:
1199                                 if (hwnd == hwndText) {
1200                                         result = wmClipboard (hwnd, msg, wParam, lParam);
1201                                 }
1202                                 break;
1203                 }
1204                 if (result != null) return result.value;
1205                 return callWindowProc (hwnd, msg, wParam, lParam);
1206         }
1207         return super.windowProc (hwnd, msg, wParam, lParam);
1208 }
1209
1210 @Override
1211 LRESULT WM_ERASEBKGND (long wParam, long lParam) {
1212         super.WM_ERASEBKGND (wParam, lParam);
1213         drawBackground (wParam);
1214         return LRESULT.ONE;
1215 }
1216
1217 @Override
1218 LRESULT WM_KILLFOCUS (long wParam, long lParam) {
1219         return null;
1220 }
1221
1222 @Override
1223 LRESULT WM_SETFOCUS (long wParam, long lParam) {
1224         OS.SetFocus (hwndText);
1225         OS.SendMessage (hwndText, OS.EM_SETSEL, 0, -1);
1226         return null;
1227 }
1228
1229 @Override
1230 LRESULT WM_SETFONT (long wParam, long lParam) {
1231         LRESULT result = super.WM_SETFONT (wParam, lParam);
1232         if (result != null) return result;
1233         OS.SendMessage (hwndText, OS.WM_SETFONT, wParam, lParam);
1234         return result;
1235 }
1236
1237 @Override
1238 LRESULT WM_SIZE (long wParam, long lParam) {
1239         LRESULT result = super.WM_SIZE (wParam, lParam);
1240         if (isDisposed ()) return result;
1241         int width = OS.LOWORD (lParam), height = OS.HIWORD (lParam);
1242         int upDownWidth = OS.GetSystemMetrics (OS.SM_CXVSCROLL);
1243         int textWidth = width - upDownWidth;
1244         int border = OS.GetSystemMetrics (OS.SM_CXEDGE);
1245         int flags = OS.SWP_NOZORDER | OS.SWP_DRAWFRAME | OS.SWP_NOACTIVATE;
1246         OS.SetWindowPos (hwndText, 0, 0, 0, textWidth + border, height, flags);
1247         OS.SetWindowPos (hwndUpDown, 0, textWidth, 0, upDownWidth, height, flags);
1248         return result;
1249 }
1250
1251 @Override
1252 LRESULT wmIMEChar(long hwnd, long wParam, long lParam) {
1253
1254         /* Process a DBCS character */
1255         Display display = this.display;
1256         display.lastKey = 0;
1257         display.lastAscii = (int)wParam;
1258         display.lastVirtual = display.lastNull = display.lastDead = false;
1259         if (!sendKeyEvent (SWT.KeyDown, OS.WM_IME_CHAR, wParam, lParam)) {
1260                 return LRESULT.ZERO;
1261         }
1262
1263         /*
1264         * Feature in Windows.  The Windows text widget uses
1265         * two 2 WM_CHAR's to process a DBCS key instead of
1266         * using WM_IME_CHAR.  The fix is to allow the text
1267         * widget to get the WM_CHAR's but ignore sending
1268         * them to the application.
1269         */
1270         ignoreCharacter = true;
1271         long result = callWindowProc (hwnd, OS.WM_IME_CHAR, wParam, lParam);
1272         MSG msg = new MSG ();
1273         int flags = OS.PM_REMOVE | OS.PM_NOYIELD | OS.PM_QS_INPUT | OS.PM_QS_POSTMESSAGE;
1274         while (OS.PeekMessage (msg, hwnd, OS.WM_CHAR, OS.WM_CHAR, flags)) {
1275                 OS.TranslateMessage (msg);
1276                 OS.DispatchMessage (msg);
1277         }
1278         ignoreCharacter = false;
1279
1280         sendKeyEvent (SWT.KeyUp, OS.WM_IME_CHAR, wParam, lParam);
1281         // widget could be disposed at this point
1282         display.lastKey = display.lastAscii = 0;
1283         return new LRESULT (result);
1284 }
1285
1286 @Override
1287 LRESULT wmChar (long hwnd, long wParam, long lParam) {
1288         if (ignoreCharacter) return null;
1289         LRESULT result = super.wmChar (hwnd, wParam, lParam);
1290         if (result != null) return result;
1291         /*
1292         * Feature in Windows.  For some reason, when the
1293         * widget is a single line text widget, when the
1294         * user presses tab, return or escape, Windows beeps.
1295         * The fix is to look for these keys and not call
1296         * the window proc.
1297         */
1298         switch ((int)wParam) {
1299                 case SWT.CR:
1300                         sendSelectionEvent (SWT.DefaultSelection);
1301                         // FALL THROUGH
1302                 case SWT.TAB:
1303                 case SWT.ESC: return LRESULT.ZERO;
1304         }
1305         return result;
1306 }
1307
1308 LRESULT wmClipboard (long hwndText, int msg, long wParam, long lParam) {
1309         if ((style & SWT.READ_ONLY) != 0) return null;
1310 //      if (!hooks (SWT.Verify) && !filters (SWT.Verify)) return null;
1311         boolean call = false;
1312         int [] start = new int [1], end = new int [1];
1313         String newText = null;
1314         switch (msg) {
1315                 case OS.WM_CLEAR:
1316                 case OS.WM_CUT:
1317                         OS.SendMessage (hwndText, OS.EM_GETSEL, start, end);
1318                         if (start [0] != end [0]) {
1319                                 newText = "";
1320                                 call = true;
1321                         }
1322                         break;
1323                 case OS.WM_PASTE:
1324                         OS.SendMessage (hwndText, OS.EM_GETSEL, start, end);
1325                         newText = getClipboardText ();
1326                         break;
1327                 case OS.EM_UNDO:
1328                 case OS.WM_UNDO:
1329                         if (OS.SendMessage (hwndText, OS.EM_CANUNDO, 0, 0) != 0) {
1330                                 ignoreModify = true;
1331                                 OS.CallWindowProc (EditProc, hwndText, msg, wParam, lParam);
1332                                 int length = OS.GetWindowTextLength (hwndText);
1333                                 int [] newStart = new int [1], newEnd = new int [1];
1334                                 OS.SendMessage (hwndText, OS.EM_GETSEL, newStart, newEnd);
1335                                 if (length != 0 && newStart [0] != newEnd [0]) {
1336                                         char [] buffer = new char [length + 1];
1337                                         OS.GetWindowText (hwndText, buffer, length + 1);
1338                                         newText = new String (buffer, newStart [0], newEnd [0] - newStart [0]);
1339                                 } else {
1340                                         newText = "";
1341                                 }
1342                                 OS.CallWindowProc (EditProc, hwndText, msg, wParam, lParam);
1343                                 OS.SendMessage (hwndText, OS.EM_GETSEL, start, end);
1344                                 ignoreModify = false;
1345                         }
1346                         break;
1347         }
1348         if (newText != null) {
1349                 String oldText = newText;
1350                 newText = verifyText (newText, start [0], end [0], null);
1351                 if (newText == null) return LRESULT.ZERO;
1352                 if (!newText.equals (oldText)) {
1353                         if (call) {
1354                                 OS.CallWindowProc (EditProc, hwndText, msg, wParam, lParam);
1355                         }
1356                         TCHAR buffer = new TCHAR (getCodePage (), newText, true);
1357                         if (msg == OS.WM_SETTEXT) {
1358                                 long hHeap = OS.GetProcessHeap ();
1359                                 int byteCount = buffer.length () * TCHAR.sizeof;
1360                                 long pszText = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
1361                                 OS.MoveMemory (pszText, buffer, byteCount);
1362                                 long code = OS.CallWindowProc (EditProc, hwndText, msg, wParam, pszText);
1363                                 OS.HeapFree (hHeap, 0, pszText);
1364                                 return new LRESULT (code);
1365                         } else {
1366                                 OS.SendMessage (hwndText, OS.EM_REPLACESEL, 0, buffer);
1367                                 return LRESULT.ZERO;
1368                         }
1369                 }
1370         }
1371         return null;
1372 }
1373
1374 @Override
1375 LRESULT wmCommandChild (long wParam, long lParam) {
1376         int code = OS.HIWORD (wParam);
1377         switch (code) {
1378                 case OS.EN_CHANGE:
1379                         if (ignoreModify) break;
1380                         boolean [] parseFail = new boolean [1];
1381                         int value = getSelectionText (parseFail);
1382                         if (!parseFail [0]) {
1383                                 int pos = (int)OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0);
1384                                 if (pos != value) setSelection (value, true, false, true);
1385                         }
1386                         sendEvent (SWT.Modify);
1387                         if (isDisposed ()) return LRESULT.ZERO;
1388                         break;
1389         }
1390         return super.wmCommandChild (wParam, lParam);
1391 }
1392
1393 @Override
1394 LRESULT wmKeyDown (long hwnd, long wParam, long lParam) {
1395         if (ignoreCharacter) return null;
1396         LRESULT result = super.wmKeyDown (hwnd, wParam, lParam);
1397         if (result != null) return result;
1398
1399         /* Increment the value */
1400         UDACCEL udaccel = new UDACCEL ();
1401         OS.SendMessage (hwndUpDown, OS.UDM_GETACCEL, 1, udaccel);
1402         int delta = 0;
1403         switch ((int)wParam) {
1404                 case OS.VK_UP: delta = udaccel.nInc; break;
1405                 case OS.VK_DOWN: delta = -udaccel.nInc; break;
1406                 case OS.VK_PRIOR: delta = pageIncrement; break;
1407                 case OS.VK_NEXT: delta = -pageIncrement; break;
1408         }
1409         if (delta != 0) {
1410                 boolean [] parseFail = new boolean [1];
1411                 int value = getSelectionText (parseFail);
1412                 if (parseFail [0]) {
1413                         value = (int)OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0);
1414                 }
1415                 int newValue = value + delta;
1416                 int [] max = new int [1], min = new int [1];
1417                 OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, min, max);
1418                 if ((style & SWT.WRAP) != 0) {
1419                         if (newValue < min [0]) newValue = max [0];
1420                         if (newValue > max [0]) newValue = min [0];
1421                 }
1422                 newValue = Math.min (Math.max (min [0], newValue), max [0]);
1423                 if (value != newValue) setSelection (newValue, true, true, true);
1424         }
1425
1426         /*  Stop the edit control from moving the caret */
1427         switch ((int)wParam) {
1428                 case OS.VK_UP:
1429                 case OS.VK_DOWN:
1430                         return LRESULT.ZERO;
1431         }
1432         return result;
1433 }
1434
1435 @Override
1436 LRESULT wmKillFocus (long hwnd, long wParam, long lParam) {
1437         boolean [] parseFail = new boolean [1];
1438         int value = getSelectionText (parseFail);
1439         if (parseFail [0]) {
1440                 value = (int)OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0);
1441                 setSelection (value, false, true, false);
1442         }
1443         return super.wmKillFocus (hwnd, wParam, lParam);
1444 }
1445
1446 @Override
1447 LRESULT wmNotifyChild (NMHDR hdr, long wParam, long lParam) {
1448         switch (hdr.code) {
1449                 case OS.UDN_DELTAPOS:
1450                         NMUPDOWN lpnmud = new NMUPDOWN ();
1451                         OS.MoveMemory (lpnmud, lParam, NMUPDOWN.sizeof);
1452                         int value = lpnmud.iPos + lpnmud.iDelta;
1453                         int [] max = new int [1], min = new int [1];
1454                         OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, min, max);
1455                         if ((style & SWT.WRAP) != 0) {
1456                                 if (value < min [0]) value = max [0];
1457                                 if (value > max [0]) value = min [0];
1458                         }
1459                         /*
1460                         * The SWT.Modify event is sent after the widget has been
1461                         * updated with the new state.  Rather than allowing
1462                         * the default updown window proc to set the value
1463                         * when the user clicks on the updown control, set
1464                         * the value explicitly and stop the window proc
1465                         * from running.
1466                         */
1467                         value = Math.min (Math.max (min [0], value), max [0]);
1468                         if (value != lpnmud.iPos) {
1469                                 setSelection (value, true, true, true);
1470                         }
1471                         return LRESULT.ONE;
1472         }
1473         return super.wmNotifyChild (hdr, wParam, lParam);
1474 }
1475
1476 @Override
1477 LRESULT wmScrollChild (long wParam, long lParam) {
1478         int code = OS.LOWORD (wParam);
1479         switch (code) {
1480                 case OS.SB_THUMBPOSITION:
1481                         sendSelectionEvent (SWT.Selection);
1482                         break;
1483         }
1484         return super.wmScrollChild (wParam, lParam);
1485 }
1486
1487 }