KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > swt > widgets > Spinner


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.swt.widgets;
12
13
14 import org.eclipse.swt.*;
15 import org.eclipse.swt.internal.win32.*;
16 import org.eclipse.swt.graphics.*;
17 import org.eclipse.swt.events.*;
18
19 /**
20  * Instances of this class are selectable user interface
21  * objects that allow the user to enter and modify numeric
22  * values.
23  * <p>
24  * Note that although this class is a subclass of <code>Composite</code>,
25  * it does not make sense to add children to it, or set a layout on it.
26  * </p><p>
27  * <dl>
28  * <dt><b>Styles:</b></dt>
29  * <dd>READ_ONLY, WRAP</dd>
30  * <dt><b>Events:</b></dt>
31  * <dd>Selection, Modify, Verify</dd>
32  * </dl>
33  * </p><p>
34  * IMPORTANT: This class is <em>not</em> intended to be subclassed.
35  * </p>
36  *
37  * @since 3.1
38  */

39 public class Spinner extends Composite {
40     int hwndText, hwndUpDown;
41     boolean ignoreModify;
42     int pageIncrement, digits;
43     static final int EditProc;
44     static final TCHAR EditClass = new TCHAR (0, "EDIT", true);
45     static final int UpDownProc;
46     static final TCHAR UpDownClass = new TCHAR (0, OS.UPDOWN_CLASS, true);
47     static {
48         WNDCLASS lpWndClass = new WNDCLASS ();
49         OS.GetClassInfo (0, EditClass, lpWndClass);
50         EditProc = lpWndClass.lpfnWndProc;
51         OS.GetClassInfo (0, UpDownClass, lpWndClass);
52         UpDownProc = lpWndClass.lpfnWndProc;
53     }
54     
55 /**
56  * Constructs a new instance of this class given its parent
57  * and a style value describing its behavior and appearance.
58  * <p>
59  * The style value is either one of the style constants defined in
60  * class <code>SWT</code> which is applicable to instances of this
61  * class, or must be built by <em>bitwise OR</em>'ing together
62  * (that is, using the <code>int</code> "|" operator) two or more
63  * of those <code>SWT</code> style constants. The class description
64  * lists the style constants that are applicable to the class.
65  * Style bits are also inherited from superclasses.
66  * </p>
67  *
68  * @param parent a composite control which will be the parent of the new instance (cannot be null)
69  * @param style the style of control to construct
70  *
71  * @exception IllegalArgumentException <ul>
72  * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
73  * </ul>
74  * @exception SWTException <ul>
75  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
76  * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
77  * </ul>
78  *
79  * @see SWT#READ_ONLY
80  * @see SWT#WRAP
81  * @see Widget#checkSubclass
82  * @see Widget#getStyle
83  */

84 public Spinner (Composite parent, int style) {
85     super (parent, checkStyle (style));
86 }
87
88 int callWindowProc (int hwnd, int msg, int wParam, int lParam) {
89     if (handle == 0) return 0;
90     if (hwnd == hwndText) {
91         return OS.CallWindowProc (EditProc, hwnd, msg, wParam, lParam);
92     }
93     if (hwnd == hwndUpDown) {
94         return OS.CallWindowProc (UpDownProc, hwnd, msg, wParam, lParam);
95     }
96     return OS.DefWindowProc (handle, msg, wParam, lParam);
97 }
98
99 static int checkStyle (int style) {
100     /*
101     * Even though it is legal to create this widget
102     * with scroll bars, they serve no useful purpose
103     * because they do not automatically scroll the
104     * widget's client area. The fix is to clear
105     * the SWT style.
106     */

107     return style & ~(SWT.H_SCROLL | SWT.V_SCROLL);
108 }
109
110 boolean checkHandle (int hwnd) {
111     return hwnd == handle || hwnd == hwndText || hwnd == hwndUpDown;
112 }
113
114 protected void checkSubclass () {
115     if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
116 }
117
118 void createHandle () {
119     super.createHandle ();
120     state &= ~(CANVAS | THEME_BACKGROUND);
121     int hInstance = OS.GetModuleHandle (null);
122     int textExStyle = (style & SWT.BORDER) != 0 ? OS.WS_EX_CLIENTEDGE : 0;
123     int textStyle = OS.WS_CHILD | OS.WS_VISIBLE | OS.ES_AUTOHSCROLL | OS.WS_CLIPSIBLINGS;
124     if ((style & SWT.READ_ONLY) != 0) textStyle |= OS.ES_READONLY;
125     if (OS.WIN32_VERSION >= OS.VERSION (4, 10)) {
126         if ((style & SWT.RIGHT_TO_LEFT) != 0) textExStyle |= OS.WS_EX_LAYOUTRTL;
127     }
128     hwndText = OS.CreateWindowEx (
129         textExStyle,
130         EditClass,
131         null,
132         textStyle,
133         0, 0, 0, 0,
134         handle,
135         0,
136         hInstance,
137         null);
138     if (hwndText == 0) error (SWT.ERROR_NO_HANDLES);
139     OS.SetWindowLong (hwndText, OS.GWL_ID, hwndText);
140     int upDownStyle = OS.WS_CHILD | OS.WS_VISIBLE | OS.UDS_AUTOBUDDY;
141     if ((style & SWT.WRAP) != 0) upDownStyle |= OS.UDS_WRAP;
142     if ((style & SWT.BORDER) != 0) {
143         if ((style & SWT.RIGHT_TO_LEFT) != 0) {
144             upDownStyle |= OS.UDS_ALIGNLEFT;
145         } else {
146             upDownStyle |= OS.UDS_ALIGNRIGHT;
147         }
148     }
149     hwndUpDown = OS.CreateWindowEx (
150         0,
151         UpDownClass,
152         null,
153         upDownStyle,
154         0, 0, 0, 0,
155         handle,
156         0,
157         hInstance,
158         null);
159     if (hwndUpDown == 0) error (SWT.ERROR_NO_HANDLES);
160     int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE;
161     SetWindowPos (hwndText, hwndUpDown, 0, 0, 0, 0, flags);
162     OS.SetWindowLong (hwndUpDown, OS.GWL_ID, hwndUpDown);
163     if (OS.IsDBLocale) {
164         int hIMC = OS.ImmGetContext (handle);
165         OS.ImmAssociateContext (hwndText, hIMC);
166         OS.ImmAssociateContext (hwndUpDown, hIMC);
167         OS.ImmReleaseContext (handle, hIMC);
168     }
169     OS.SendMessage (hwndUpDown, OS.UDM_SETRANGE32, 0, 100);
170     OS.SendMessage (hwndUpDown, OS.IsWinCE ? OS.UDM_SETPOS : OS.UDM_SETPOS32, 0, 0);
171     pageIncrement = 10;
172     digits = 0;
173     TCHAR buffer = new TCHAR (getCodePage (), "0", true);
174     OS.SetWindowText (hwndText, buffer);
175 }
176
177 /**
178  * Adds the listener to the collection of listeners who will
179  * be notified when the receiver's text is modified, by sending
180  * it one of the messages defined in the <code>ModifyListener</code>
181  * interface.
182  *
183  * @param listener the listener which should be notified
184  *
185  * @exception IllegalArgumentException <ul>
186  * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
187  * </ul>
188  * @exception SWTException <ul>
189  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
190  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
191  * </ul>
192  *
193  * @see ModifyListener
194  * @see #removeModifyListener
195  */

196 public void addModifyListener (ModifyListener listener) {
197     checkWidget ();
198     if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
199     TypedListener typedListener = new TypedListener (listener);
200     addListener (SWT.Modify, typedListener);
201 }
202
203 /**
204  * Adds the listener to the collection of listeners who will
205  * be notified when the control is selected by the user, by sending
206  * it one of the messages defined in the <code>SelectionListener</code>
207  * interface.
208  * <p>
209  * <code>widgetSelected</code> is not called for texts.
210  * <code>widgetDefaultSelected</code> is typically called when ENTER is pressed in a single-line text.
211  * </p>
212  *
213  * @param listener the listener which should be notified when the control is selected by the user
214  *
215  * @exception IllegalArgumentException <ul>
216  * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
217  * </ul>
218  * @exception SWTException <ul>
219  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
220  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
221  * </ul>
222  *
223  * @see SelectionListener
224  * @see #removeSelectionListener
225  * @see SelectionEvent
226  */

227 public void addSelectionListener(SelectionListener listener) {
228     checkWidget ();
229     if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
230     TypedListener typedListener = new TypedListener (listener);
231     addListener (SWT.Selection,typedListener);
232     addListener (SWT.DefaultSelection,typedListener);
233 }
234
235 /**
236  * Adds the listener to the collection of listeners who will
237  * be notified when the receiver's text is verified, by sending
238  * it one of the messages defined in the <code>VerifyListener</code>
239  * interface.
240  *
241  * @param listener the listener which should be notified
242  *
243  * @exception IllegalArgumentException <ul>
244  * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
245  * </ul>
246  * @exception SWTException <ul>
247  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
248  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
249  * </ul>
250  *
251  * @see VerifyListener
252  * @see #removeVerifyListener
253  */

254 void addVerifyListener (VerifyListener listener) {
255     checkWidget();
256     if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
257     TypedListener typedListener = new TypedListener (listener);
258     addListener (SWT.Verify, typedListener);
259 }
260
261 int borderHandle () {
262     return hwndText;
263 }
264
265 public Point computeSize (int wHint, int hHint, boolean changed) {
266     checkWidget ();
267     int width = 0, height = 0;
268     if (wHint == SWT.DEFAULT || hHint == SWT.DEFAULT) {
269         int newFont, oldFont = 0;
270         int hDC = OS.GetDC (hwndText);
271         newFont = OS.SendMessage (hwndText, OS.WM_GETFONT, 0, 0);
272         if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
273         TEXTMETRIC tm = OS.IsUnicode ? (TEXTMETRIC) new TEXTMETRICW () : new TEXTMETRICA ();
274         OS.GetTextMetrics (hDC, tm);
275         height = tm.tmHeight;
276         RECT rect = new RECT ();
277         int [] max = new int [1];
278         OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, null, max);
279         String JavaDoc string = String.valueOf (max [0]);
280         if (digits > 0) {
281             StringBuffer JavaDoc buffer = new StringBuffer JavaDoc ();
282             buffer.append (string);
283             buffer.append (getDecimalSeparator ());
284             int count = digits - string.length ();
285             while (count >= 0) {
286                 buffer.append ("0");
287                 count--;
288             }
289             string = buffer.toString ();
290         }
291         TCHAR buffer = new TCHAR (getCodePage (), string, false);
292         int flags = OS.DT_CALCRECT | OS.DT_EDITCONTROL | OS.DT_NOPREFIX;
293         OS.DrawText (hDC, buffer, buffer.length (), rect, flags);
294         width = rect.right - rect.left;
295         if (newFont != 0) OS.SelectObject (hDC, oldFont);
296         OS.ReleaseDC (hwndText, hDC);
297     }
298     if (width == 0) width = DEFAULT_WIDTH;
299     if (height == 0) height = DEFAULT_HEIGHT;
300     if (wHint != SWT.DEFAULT) width = wHint;
301     if (hHint != SWT.DEFAULT) height = hHint;
302     Rectangle trim = computeTrim (0, 0, width, height);
303     if (hHint == SWT.DEFAULT) {
304         int upDownHeight = OS.GetSystemMetrics (OS.SM_CYVSCROLL) + 2 * getBorderWidth ();
305         if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
306             upDownHeight += (style & SWT.BORDER) != 0 ? 1 : 3;
307         }
308         trim.height = Math.max (trim.height, upDownHeight);
309     }
310     return new Point (trim.width, trim.height);
311 }
312
313 public Rectangle computeTrim (int x, int y, int width, int height) {
314     checkWidget ();
315     
316     /* Get the trim of the text control */
317     RECT rect = new RECT ();
318     OS.SetRect (rect, x, y, x + width, y + height);
319     int bits0 = OS.GetWindowLong (hwndText, OS.GWL_STYLE);
320     int bits1 = OS.GetWindowLong (hwndText, OS.GWL_EXSTYLE);
321     OS.AdjustWindowRectEx (rect, bits0, false, bits1);
322     width = rect.right - rect.left;
323     height = rect.bottom - rect.top;
324     
325     /*
326     * The preferred height of a single-line text widget
327     * has been hand-crafted to be the same height as
328     * the single-line text widget in an editable combo
329     * box.
330     */

331     int margins = OS.SendMessage (hwndText, OS.EM_GETMARGINS, 0, 0);
332     x -= margins & 0xFFFF;
333     width += (margins & 0xFFFF) + ((margins >> 16) & 0xFFFF);
334     if ((style & SWT.BORDER) != 0) {
335         x -= 1;
336         y -= 1;
337         width += 2;
338         height += 2;
339     }
340     width += OS.GetSystemMetrics (OS.SM_CXVSCROLL);
341     return new Rectangle (x, y, width, height);
342 }
343
344 /**
345  * Copies the selected text.
346  * <p>
347  * The current selection is copied to the clipboard.
348  * </p>
349  *
350  * @exception SWTException <ul>
351  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
352  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
353  * </ul>
354  */

355 public void copy () {
356     checkWidget ();
357     OS.SendMessage (hwndText, OS.WM_COPY, 0, 0);
358 }
359
360 /**
361  * Cuts the selected text.
362  * <p>
363  * The current selection is first copied to the
364  * clipboard and then deleted from the widget.
365  * </p>
366  *
367  * @exception SWTException <ul>
368  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
369  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
370  * </ul>
371  */

372 public void cut () {
373     checkWidget ();
374     if ((style & SWT.READ_ONLY) != 0) return;
375     OS.SendMessage (hwndText, OS.WM_CUT, 0, 0);
376 }
377
378 int defaultBackground () {
379     return OS.GetSysColor (OS.COLOR_WINDOW);
380 }
381
382 void enableWidget (boolean enabled) {
383     super.enableWidget (enabled);
384     OS.EnableWindow (hwndText, enabled);
385     OS.EnableWindow (hwndUpDown, enabled);
386 }
387
388 void deregister () {
389     super.deregister ();
390     display.removeControl (hwndText);
391     display.removeControl (hwndUpDown);
392 }
393
394 boolean hasFocus () {
395     int hwndFocus = OS.GetFocus ();
396     if (hwndFocus == handle) return true;
397     if (hwndFocus == hwndText) return true;
398     if (hwndFocus == hwndUpDown) return true;
399     return false;
400 }
401
402 /**
403  * Returns the number of decimal places used by the receiver.
404  *
405  * @return the digits
406  *
407  * @exception SWTException <ul>
408  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
409  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
410  * </ul>
411  */

412 public int getDigits () {
413     checkWidget ();
414     return digits;
415 }
416
417 String JavaDoc getDecimalSeparator () {
418     TCHAR tchar = new TCHAR (getCodePage (), 4);
419     int size = OS.GetLocaleInfo (OS.LOCALE_USER_DEFAULT, OS.LOCALE_SDECIMAL, tchar, 4);
420     return size != 0 ? tchar.toString (0, size - 1) : ".";
421 }
422
423 /**
424  * Returns the amount that the receiver's value will be
425  * modified by when the up/down arrows are pressed.
426  *
427  * @return the increment
428  *
429  * @exception SWTException <ul>
430  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
431  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
432  * </ul>
433  */

434 public int getIncrement () {
435     checkWidget ();
436     UDACCEL udaccel = new UDACCEL ();
437     OS.SendMessage (hwndUpDown, OS.UDM_GETACCEL, 1, udaccel);
438     return udaccel.nInc;
439 }
440
441 /**
442  * Returns the maximum value which the receiver will allow.
443  *
444  * @return the maximum
445  *
446  * @exception SWTException <ul>
447  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
448  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
449  * </ul>
450  */

451 public int getMaximum () {
452     checkWidget ();
453     int [] max = new int [1];
454     OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, null, max);
455     return max [0];
456 }
457
458 /**
459  * Returns the minimum value which the receiver will allow.
460  *
461  * @return the minimum
462  *
463  * @exception SWTException <ul>
464  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
465  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
466  * </ul>
467  */

468 public int getMinimum () {
469     checkWidget ();
470     int [] min = new int [1];
471     OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, min, null);
472     return min [0];
473 }
474
475 /**
476  * Returns the amount that the receiver's position will be
477  * modified by when the page up/down keys are pressed.
478  *
479  * @return the page increment
480  *
481  * @exception SWTException <ul>
482  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
483  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
484  * </ul>
485  */

486 public int getPageIncrement () {
487     checkWidget ();
488     return pageIncrement;
489 }
490
491 /**
492  * Returns the <em>selection</em>, which is the receiver's position.
493  *
494  * @return the selection
495  *
496  * @exception SWTException <ul>
497  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
498  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
499  * </ul>
500  */

501 public int getSelection () {
502     checkWidget ();
503     if (OS.IsWinCE) {
504         return OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0) & 0xFFFF;
505     } else {
506         return OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0);
507     }
508 }
509
510 int getSelectionText () {
511     int length = OS.GetWindowTextLength (hwndText);
512     TCHAR buffer = new TCHAR (getCodePage (), length + 1);
513     OS.GetWindowText (hwndText, buffer, length + 1);
514     String JavaDoc string = buffer.toString (0, length);
515     try {
516         int value;
517         if (digits > 0) {
518             String JavaDoc decimalSeparator = getDecimalSeparator ();
519             int index = string.indexOf (decimalSeparator);
520             if (index != -1) {
521                 String JavaDoc wholePart = string.substring (0, index);
522                 String JavaDoc decimalPart = string.substring (index + 1);
523                 if (decimalPart.length () > digits) {
524                     decimalPart = decimalPart.substring (0, digits);
525                 } else {
526                     int i = digits - decimalPart.length ();
527                     for (int j = 0; j < i; j++) {
528                         decimalPart = decimalPart + "0";
529                     }
530                 }
531                 int wholeValue = Integer.parseInt (wholePart);
532                 int decimalValue = Integer.parseInt (decimalPart);
533                 for (int i = 0; i < digits; i++) wholeValue *= 10;
534                 value = wholeValue + decimalValue;
535             } else {
536                 value = Integer.parseInt (string);
537             }
538         } else {
539             value = Integer.parseInt (string);
540         }
541         int [] max = new int [1], min = new int [1];
542         OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, min, max);
543         if (min [0] <= value && value <= max [0]) return value;
544     } catch (NumberFormatException JavaDoc e) {
545     }
546     return -1;
547 }
548
549 int mbcsToWcsPos (int mbcsPos) {
550     if (mbcsPos <= 0) return 0;
551     if (OS.IsUnicode) return mbcsPos;
552     int mbcsSize = OS.GetWindowTextLengthA (hwndText);
553     if (mbcsSize == 0) return 0;
554     if (mbcsPos >= mbcsSize) return mbcsSize;
555     byte [] buffer = new byte [mbcsSize + 1];
556     OS.GetWindowTextA (hwndText, buffer, mbcsSize + 1);
557     return OS.MultiByteToWideChar (getCodePage (), OS.MB_PRECOMPOSED, buffer, mbcsPos, null, 0);
558 }
559
560 /**
561  * Pastes text from clipboard.
562  * <p>
563  * The selected text is deleted from the widget
564  * and new text inserted from the clipboard.
565  * </p>
566  *
567  * @exception SWTException <ul>
568  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
569  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
570  * </ul>
571  */

572 public void paste () {
573     checkWidget ();
574     if ((style & SWT.READ_ONLY) != 0) return;
575     OS.SendMessage (hwndText, OS.WM_PASTE, 0, 0);
576 }
577
578 void register () {
579     super.register ();
580     display.addControl (hwndText, this);
581     display.addControl (hwndUpDown, this);
582 }
583
584 void releaseHandle () {
585     super.releaseHandle ();
586     hwndText = hwndUpDown = 0;
587 }
588
589 /**
590  * Removes the listener from the collection of listeners who will
591  * be notified when the receiver's text is modified.
592  *
593  * @param listener the listener which should no longer be notified
594  *
595  * @exception IllegalArgumentException <ul>
596  * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
597  * </ul>
598  * @exception SWTException <ul>
599  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
600  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
601  * </ul>
602  *
603  * @see ModifyListener
604  * @see #addModifyListener
605  */

606 public void removeModifyListener (ModifyListener listener) {
607     checkWidget ();
608     if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
609     if (eventTable == null) return;
610     eventTable.unhook (SWT.Modify, listener);
611 }
612
613 /**
614  * Removes the listener from the collection of listeners who will
615  * be notified when the control is selected by the user.
616  *
617  * @param listener the listener which should no longer be notified
618  *
619  * @exception IllegalArgumentException <ul>
620  * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
621  * </ul>
622  * @exception SWTException <ul>
623  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
624  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
625  * </ul>
626  *
627  * @see SelectionListener
628  * @see #addSelectionListener
629  */

630 public void removeSelectionListener(SelectionListener listener) {
631     checkWidget ();
632     if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
633     if (eventTable == null) return;
634     eventTable.unhook (SWT.Selection, listener);
635     eventTable.unhook (SWT.DefaultSelection,listener);
636 }
637
638 /**
639  * Removes the listener from the collection of listeners who will
640  * be notified when the control is verified.
641  *
642  * @param listener the listener which should no longer be notified
643  *
644  * @exception IllegalArgumentException <ul>
645  * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
646  * </ul>
647  * @exception SWTException <ul>
648  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
649  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
650  * </ul>
651  *
652  * @see VerifyListener
653  * @see #addVerifyListener
654  */

655 void removeVerifyListener (VerifyListener listener) {
656     checkWidget ();
657     if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
658     if (eventTable == null) return;
659     eventTable.unhook (SWT.Verify, listener);
660 }
661
662 boolean sendKeyEvent (int type, int msg, int wParam, int lParam, Event event) {
663     if (!super.sendKeyEvent (type, msg, wParam, lParam, event)) {
664         return false;
665     }
666     if ((style & SWT.READ_ONLY) != 0) return true;
667     if (type != SWT.KeyDown) return true;
668     if (msg != OS.WM_CHAR && msg != OS.WM_KEYDOWN && msg != OS.WM_IME_CHAR) {
669         return true;
670     }
671     if (event.character == 0) return true;
672 // if (!hooks (SWT.Verify) && !filters (SWT.Verify)) return true;
673
char key = event.character;
674     int stateMask = event.stateMask;
675     
676     /*
677     * Disable all magic keys that could modify the text
678     * and don't send events when Alt, Shift or Ctrl is
679     * pressed.
680     */

681     switch (msg) {
682         case OS.WM_CHAR:
683             if (key != 0x08 && key != 0x7F && key != '\r' && key != '\t' && key != '\n') break;
684             // FALL THROUGH
685
case OS.WM_KEYDOWN:
686             if ((stateMask & (SWT.ALT | SWT.SHIFT | SWT.CONTROL)) != 0) return false;
687             break;
688     }
689
690     /*
691     * If the left button is down, the text widget refuses the character.
692     */

693     if (OS.GetKeyState (OS.VK_LBUTTON) < 0) {
694         return true;
695     }
696
697     /* Verify the character */
698     String JavaDoc oldText = "";
699     int [] start = new int [1], end = new int [1];
700     OS.SendMessage (hwndText, OS.EM_GETSEL, start, end);
701     switch (key) {
702         case 0x08: /* Bs */
703             if (start [0] == end [0]) {
704                 if (start [0] == 0) return true;
705                 start [0] = start [0] - 1;
706                 if (!OS.IsUnicode && OS.IsDBLocale) {
707                     int [] newStart = new int [1], newEnd = new int [1];
708                     OS.SendMessage (hwndText, OS.EM_SETSEL, start [0], end [0]);
709                     OS.SendMessage (hwndText, OS.EM_GETSEL, newStart, newEnd);
710                     if (start [0] != newStart [0]) start [0] = start [0] - 1;
711                 }
712                 start [0] = Math.max (start [0], 0);
713             }
714             break;
715         case 0x7F: /* Del */
716             if (start [0] == end [0]) {
717                 int length = OS.GetWindowTextLength (hwndText);
718                 if (start [0] == length) return true;
719                 end [0] = end [0] + 1;
720                 if (!OS.IsUnicode && OS.IsDBLocale) {
721                     int [] newStart = new int [1], newEnd = new int [1];
722                     OS.SendMessage (hwndText, OS.EM_SETSEL, start [0], end [0]);
723                     OS.SendMessage (hwndText, OS.EM_GETSEL, newStart, newEnd);
724                     if (end [0] != newEnd [0]) end [0] = end [0] + 1;
725                 }
726                 end [0] = Math.min (end [0], length);
727             }
728             break;
729         case '\r': /* Return */
730             return true;
731         default: /* Tab and other characters */
732             if (key != '\t' && key < 0x20) return true;
733             oldText = new String JavaDoc (new char [] {key});
734             break;
735     }
736     String JavaDoc newText = verifyText (oldText, start [0], end [0], event);
737     if (newText == null) return false;
738     if (newText == oldText) return true;
739     TCHAR buffer = new TCHAR (getCodePage (), newText, true);
740     OS.SendMessage (hwndText, OS.EM_SETSEL, start [0], end [0]);
741     OS.SendMessage (hwndText, OS.EM_REPLACESEL, 0, buffer);
742     return false;
743 }
744
745 void setBackgroundImage (int hBitmap) {
746     super.setBackgroundImage (hBitmap);
747     OS.InvalidateRect (hwndText, null, true);
748 }
749
750 void setBackgroundPixel (int pixel) {
751     super.setBackgroundPixel (pixel);
752     OS.InvalidateRect (hwndText, null, true);
753 }
754
755 /**
756  * Sets the number of decimal places used by the receiver.
757  * <p>
758  * The digit setting is used to allow for floating point values in the receiver.
759  * For example, to set the selection to a floating point value of 1.37 call setDigits() with
760  * a value of 2 and setSelection() with a value of 137. Similarly, if getDigits() has a value
761  * of 2 and getSelection() returns 137 this should be interpreted as 1.37. This applies to all
762  * numeric APIs.
763  * </p>
764  *
765  * @param value the new digits (must be greater than or equal to zero)
766  *
767  * @exception IllegalArgumentException <ul>
768  * <li>ERROR_INVALID_ARGUMENT - if the value is less than zero</li>
769  * </ul>
770  * @exception SWTException <ul>
771  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
772  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
773  * </ul>
774  */

775 public void setDigits (int value) {
776     checkWidget ();
777     if (value < 0) error (SWT.ERROR_INVALID_ARGUMENT);
778     if (value == this.digits) return;
779     this.digits = value;
780     int pos;
781     if (OS.IsWinCE) {
782         pos = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0) & 0xFFFF;
783     } else {
784         pos = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0);
785     }
786     setSelection (pos, false, true, false);
787 }
788
789 void setForegroundPixel (int pixel) {
790     super.setForegroundPixel (pixel);
791     OS.InvalidateRect (hwndText, null, true);
792 }
793
794 /**
795  * Sets the amount that the receiver's value will be
796  * modified by when the up/down arrows are pressed to
797  * the argument, which must be at least one.
798  *
799  * @param value the new increment (must be greater than zero)
800  *
801  * @exception SWTException <ul>
802  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
803  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
804  * </ul>
805  */

806 public void setIncrement (int value) {
807     checkWidget ();
808     if (value < 1) return;
809     int hHeap = OS.GetProcessHeap ();
810     int count = OS.SendMessage (hwndUpDown, OS.UDM_GETACCEL, 0, (UDACCEL)null);
811     int udaccels = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, UDACCEL.sizeof * count);
812     OS.SendMessage (hwndUpDown, OS.UDM_GETACCEL, count, udaccels);
813     int first = -1;
814     UDACCEL udaccel = new UDACCEL ();
815     for (int i = 0; i < count; i++) {
816         int offset = udaccels + (i * UDACCEL.sizeof);
817         OS.MoveMemory (udaccel, offset, UDACCEL.sizeof);
818         if (first == -1) first = udaccel.nInc;
819         udaccel.nInc = udaccel.nInc * value / first;
820         OS.MoveMemory (offset, udaccel, UDACCEL.sizeof);
821     }
822     OS.SendMessage (hwndUpDown, OS.UDM_SETACCEL, count, udaccels);
823     OS.HeapFree (hHeap, 0, udaccels);
824 }
825
826 /**
827  * Sets the maximum value that the receiver will allow. This new
828  * value will be ignored if it is not greater than the receiver's current
829  * minimum value. If the new maximum is applied then the receiver's
830  * selection value will be adjusted if necessary to fall within its new range.
831  *
832  * @param value the new maximum, which must be greater than the current minimum
833  *
834  * @exception SWTException <ul>
835  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
836  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
837  * </ul>
838  */

839 public void setMaximum (int value) {
840     checkWidget ();
841     if (value < 0) return;
842     int [] min = new int [1];
843     OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, min, null);
844     if (value <= min [0]) return;
845     int pos;
846     if (OS.IsWinCE) {
847         pos = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0) & 0xFFFF;
848     } else {
849         pos = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0);
850     }
851     OS.SendMessage (hwndUpDown , OS.UDM_SETRANGE32, min [0], value);
852     if (pos > value) setSelection (value, true, true, false);
853 }
854
855 /**
856  * Sets the minimum value that the receiver will allow. This new
857  * value will be ignored if it is negative or is not less than the receiver's
858  * current maximum value. If the new minimum is applied then the receiver's
859  * selection value will be adjusted if necessary to fall within its new range.
860  *
861  * @param value the new minimum, which must be nonnegative and less than the current maximum
862  *
863  * @exception SWTException <ul>
864  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
865  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
866  * </ul>
867  */

868 public void setMinimum (int value) {
869     checkWidget ();
870     if (value < 0) return;
871     int [] max = new int [1];
872     OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, null, max);
873     if (value >= max [0]) return;
874     int pos;
875     if (OS.IsWinCE) {
876         pos = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0) & 0xFFFF;
877     } else {
878         pos = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0);
879     }
880     OS.SendMessage (hwndUpDown , OS.UDM_SETRANGE32, value, max [0]);
881     if (pos < value) setSelection (value, true, true, false);
882 }
883
884 /**
885  * Sets the amount that the receiver's position will be
886  * modified by when the page up/down keys are pressed
887  * to the argument, which must be at least one.
888  *
889  * @param value the page increment (must be greater than zero)
890  *
891  * @exception SWTException <ul>
892  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
893  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
894  * </ul>
895  */

896 public void setPageIncrement (int value) {
897     checkWidget ();
898     if (value < 1) return;
899     pageIncrement = value;
900 }
901
902 /**
903  * Sets the <em>selection</em>, which is the receiver's
904  * position, to the argument. If the argument is not within
905  * the range specified by minimum and maximum, it will be
906  * adjusted to fall within this range.
907  *
908  * @param value the new selection (must be zero or greater)
909  *
910  * @exception SWTException <ul>
911  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
912  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
913  * </ul>
914  */

915 public void setSelection (int value) {
916     checkWidget ();
917     int [] max = new int [1], min = new int [1];
918     OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, min, max);
919     value = Math.min (Math.max (min [0], value), max [0]);
920     setSelection (value, true, true, false);
921 }
922
923 void setSelection (int value, boolean setPos, boolean setText, boolean notify) {
924     if (setPos) {
925         OS.SendMessage (hwndUpDown , OS.IsWinCE ? OS.UDM_SETPOS : OS.UDM_SETPOS32, 0, value);
926     }
927     if (setText) {
928         String JavaDoc string = String.valueOf (value);
929         if (digits > 0) {
930             String JavaDoc decimalSeparator = getDecimalSeparator ();
931             int index = string.length () - digits;
932             StringBuffer JavaDoc buffer = new StringBuffer JavaDoc ();
933             if (index > 0) {
934                 buffer.append (string.substring (0, index));
935                 buffer.append (decimalSeparator);
936                 buffer.append (string.substring (index));
937             } else {
938                 buffer.append ("0");
939                 buffer.append (decimalSeparator);
940                 while (index++ < 0) buffer.append ("0");
941                 buffer.append (string);
942             }
943             string = buffer.toString ();
944         }
945         if (hooks (SWT.Verify) || filters (SWT.Verify)) {
946             int length = OS.GetWindowTextLength (hwndText);
947             string = verifyText (string, 0, length, null);
948             if (string == null) return;
949         }
950         TCHAR buffer = new TCHAR (getCodePage (), string, true);
951         OS.SetWindowText (hwndText, buffer);
952     }
953     if (notify) postEvent (SWT.Selection);
954 }
955
956 void setToolTipText (Shell shell, String JavaDoc string) {
957     shell.setToolTipText (hwndText, string);
958     shell.setToolTipText (hwndUpDown, string);
959 }
960
961 /**
962  * Sets the receiver's selection, minimum value, maximum
963  * value, digits, increment and page increment all at once.
964  * <p>
965  * Note: This is similar to setting the values individually
966  * using the appropriate methods, but may be implemented in a
967  * more efficient fashion on some platforms.
968  * </p>
969  *
970  * @param selection the new selection value
971  * @param minimum the new minimum value
972  * @param maximum the new maximum value
973  * @param digits the new digits value
974  * @param increment the new increment value
975  * @param pageIncrement the new pageIncrement value
976  *
977  * @exception SWTException <ul>
978  * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
979  * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
980  * </ul>
981  *
982  * @since 3.2
983  */

984 public void setValues (int selection, int minimum, int maximum, int digits, int increment, int pageIncrement) {
985     checkWidget ();
986     if (minimum < 0) return;
987     if (maximum <= minimum) return;
988     if (digits < 0) return;
989     if (increment < 1) return;
990     if (pageIncrement < 1) return;
991     selection = Math.min (Math.max (minimum, selection), maximum);
992     setIncrement (increment);
993     this.pageIncrement = pageIncrement;
994     this.digits = digits;
995     OS.SendMessage (hwndUpDown , OS.UDM_SETRANGE32, minimum, maximum);
996     setSelection (selection, true, true, false);
997 }
998
999 void subclass () {
1000    super.subclass ();
1001    int newProc = display.windowProc;
1002    OS.SetWindowLong (hwndText, OS.GWL_WNDPROC, newProc);
1003    OS.SetWindowLong (hwndUpDown, OS.GWL_WNDPROC, newProc);
1004}
1005
1006void unsubclass () {
1007    super.unsubclass ();
1008    OS.SetWindowLong (hwndText, OS.GWL_WNDPROC, EditProc);
1009    OS.SetWindowLong (hwndUpDown, OS.GWL_WNDPROC, UpDownProc);
1010}
1011
1012String JavaDoc verifyText (String JavaDoc string, int start, int end, Event keyEvent) {
1013    Event event = new Event ();
1014    event.text = string;
1015    event.start = start;
1016    event.end = end;
1017    if (keyEvent != null) {
1018        event.character = keyEvent.character;
1019        event.keyCode = keyEvent.keyCode;
1020        event.stateMask = keyEvent.stateMask;
1021    }
1022    int index = 0;
1023    if (digits > 0) {
1024        String JavaDoc decimalSeparator = getDecimalSeparator ();
1025        index = string.indexOf (decimalSeparator);
1026        if (index != -1) {
1027            string = string.substring (0, index) + string.substring (index + 1);
1028        }
1029        index = 0;
1030    }
1031    while (index < string.length ()) {
1032        if (!Character.isDigit (string.charAt (index))) break;
1033        index++;
1034    }
1035    event.doit = index == string.length ();
1036    if (!OS.IsUnicode && OS.IsDBLocale) {
1037        event.start = mbcsToWcsPos (start);
1038        event.end = mbcsToWcsPos (end);
1039    }
1040    sendEvent (SWT.Verify, event);
1041    if (!event.doit || isDisposed ()) return null;
1042    return event.text;
1043}
1044
1045int widgetExtStyle () {
1046    return super.widgetExtStyle () & ~OS.WS_EX_CLIENTEDGE;
1047}
1048
1049int windowProc (int hwnd, int msg, int wParam, int lParam) {
1050    if (hwnd == hwndText || hwnd == hwndUpDown) {
1051        LRESULT result = null;
1052        switch (msg) {
1053            /* Keyboard messages */
1054            case OS.WM_CHAR: result = wmChar (hwnd, wParam, lParam); break;
1055            case OS.WM_IME_CHAR: result = wmIMEChar (hwnd, wParam, lParam); break;
1056            case OS.WM_KEYDOWN: result = wmKeyDown (hwnd, wParam, lParam); break;
1057            case OS.WM_KEYUP: result = wmKeyUp (hwnd, wParam, lParam); break;
1058            case OS.WM_SYSCHAR: result = wmSysChar (hwnd, wParam, lParam); break;
1059            case OS.WM_SYSKEYDOWN: result = wmSysKeyDown (hwnd, wParam, lParam); break;
1060            case OS.WM_SYSKEYUP: result = wmSysKeyUp (hwnd, wParam, lParam); break;
1061    
1062            /* Mouse Messages */
1063            case OS.WM_CAPTURECHANGED: result = wmCaptureChanged (hwnd, wParam, lParam); break;
1064            case OS.WM_LBUTTONDBLCLK: result = wmLButtonDblClk (hwnd, wParam, lParam); break;
1065            case OS.WM_LBUTTONDOWN: result = wmLButtonDown (hwnd, wParam, lParam); break;
1066            case OS.WM_LBUTTONUP: result = wmLButtonUp (hwnd, wParam, lParam); break;
1067            case OS.WM_MBUTTONDBLCLK: result = wmMButtonDblClk (hwnd, wParam, lParam); break;
1068            case OS.WM_MBUTTONDOWN: result = wmMButtonDown (hwnd, wParam, lParam); break;
1069            case OS.WM_MBUTTONUP: result = wmMButtonUp (hwnd, wParam, lParam); break;
1070            case OS.WM_MOUSEHOVER: result = wmMouseHover (hwnd, wParam, lParam); break;
1071            case OS.WM_MOUSELEAVE: result = wmMouseLeave (hwnd, wParam, lParam); break;
1072            case OS.WM_MOUSEMOVE: result = wmMouseMove (hwnd, wParam, lParam); break;
1073// case OS.WM_MOUSEWHEEL: result = wmMouseWheel (hwnd, wParam, lParam); break;
1074
case OS.WM_RBUTTONDBLCLK: result = wmRButtonDblClk (hwnd, wParam, lParam); break;
1075            case OS.WM_RBUTTONDOWN: result = wmRButtonDown (hwnd, wParam, lParam); break;
1076            case OS.WM_RBUTTONUP: result = wmRButtonUp (hwnd, wParam, lParam); break;
1077            case OS.WM_XBUTTONDBLCLK: result = wmXButtonDblClk (hwnd, wParam, lParam); break;
1078            case OS.WM_XBUTTONDOWN: result = wmXButtonDown (hwnd, wParam, lParam); break;
1079            case OS.WM_XBUTTONUP: result = wmXButtonUp (hwnd, wParam, lParam); break;
1080            
1081            /* Focus Messages */
1082            case OS.WM_SETFOCUS: result = wmSetFocus (hwnd, wParam, lParam); break;
1083            case OS.WM_KILLFOCUS: result = wmKillFocus (hwnd, wParam, lParam); break;
1084    
1085            /* Paint messages */
1086            case OS.WM_PAINT: result = wmPaint (hwnd, wParam, lParam); break;
1087            case OS.WM_PRINT: result = wmPrint (hwnd, wParam, lParam); break;
1088    
1089            /* Menu messages */
1090            case OS.WM_CONTEXTMENU: result = wmContextMenu (hwnd, wParam, lParam); break;
1091                
1092            /* Clipboard messages */
1093            case OS.WM_CLEAR:
1094            case OS.WM_CUT:
1095            case OS.WM_PASTE:
1096            case OS.WM_UNDO:
1097            case OS.EM_UNDO:
1098                if (hwnd == hwndText) {
1099                    result = wmClipboard (hwnd, msg, wParam, lParam);
1100                }
1101                break;
1102        }
1103        if (result != null) return result.value;
1104        return callWindowProc (hwnd, msg, wParam, lParam);
1105    }
1106    return super.windowProc (hwnd, msg, wParam, lParam);
1107}
1108
1109LRESULT WM_ERASEBKGND (int wParam, int lParam) {
1110    super.WM_ERASEBKGND (wParam, lParam);
1111    drawBackground (wParam);
1112    return LRESULT.ONE;
1113}
1114
1115LRESULT WM_KILLFOCUS (int wParam, int lParam) {
1116    return null;
1117}
1118
1119LRESULT WM_SETFOCUS (int wParam, int lParam) {
1120    OS.SetFocus (hwndText);
1121    return null;
1122}
1123
1124LRESULT WM_SETFONT (int wParam, int lParam) {
1125    LRESULT result = super.WM_SETFONT (wParam, lParam);
1126    if (result != null) return result;
1127    OS.SendMessage (hwndText, OS.WM_SETFONT, wParam, lParam);
1128    return result;
1129}
1130
1131LRESULT WM_SIZE (int wParam, int lParam) {
1132    LRESULT result = super.WM_SIZE (wParam, lParam);
1133    if (isDisposed ()) return result;
1134    int width = lParam & 0xFFFF, height = lParam >> 16;
1135    int upDownWidth = OS.GetSystemMetrics (OS.SM_CXVSCROLL);
1136    int textWidth = width - upDownWidth;
1137    int border = OS.GetSystemMetrics (OS.SM_CXEDGE);
1138    int flags = OS.SWP_NOZORDER | OS.SWP_DRAWFRAME | OS.SWP_NOACTIVATE;
1139    SetWindowPos (hwndText, 0, 0, 0, textWidth + border, height, flags);
1140    SetWindowPos (hwndUpDown, 0, textWidth, 0, upDownWidth, height, flags);
1141    return result;
1142}
1143
1144LRESULT wmChar (int hwnd, int wParam, int lParam) {
1145    LRESULT result = super.wmChar (hwnd, wParam, lParam);
1146    if (result != null) return result;
1147    /*
1148    * Feature in Windows. For some reason, when the
1149    * widget is a single line text widget, when the
1150    * user presses tab, return or escape, Windows beeps.
1151    * The fix is to look for these keys and not call
1152    * the window proc.
1153    */

1154    switch (wParam) {
1155        case SWT.CR:
1156            postEvent (SWT.DefaultSelection);
1157            // FALL THROUGH
1158
case SWT.TAB:
1159        case SWT.ESC: return LRESULT.ZERO;
1160    }
1161    return result;
1162}
1163
1164LRESULT wmClipboard (int hwndText, int msg, int wParam, int lParam) {
1165    if ((style & SWT.READ_ONLY) != 0) return null;
1166// if (!hooks (SWT.Verify) && !filters (SWT.Verify)) return null;
1167
boolean call = false;
1168    int [] start = new int [1], end = new int [1];
1169    String JavaDoc newText = null;
1170    switch (msg) {
1171        case OS.WM_CLEAR:
1172        case OS.WM_CUT:
1173            OS.SendMessage (hwndText, OS.EM_GETSEL, start, end);
1174            if (start [0] != end [0]) {
1175                newText = "";
1176                call = true;
1177            }
1178            break;
1179        case OS.WM_PASTE:
1180            OS.SendMessage (hwndText, OS.EM_GETSEL, start, end);
1181            newText = getClipboardText ();
1182            break;
1183        case OS.EM_UNDO:
1184        case OS.WM_UNDO:
1185            if (OS.SendMessage (hwndText, OS.EM_CANUNDO, 0, 0) != 0) {
1186                ignoreModify = true;
1187                OS.SendMessage (hwndText, OS.EM_GETSEL, start, end);
1188                OS.CallWindowProc (EditProc, hwndText, msg, wParam, lParam);
1189                int length = OS.GetWindowTextLength (hwndText);
1190                int [] newStart = new int [1], newEnd = new int [1];
1191                OS.SendMessage (hwndText, OS.EM_GETSEL, newStart, newEnd);
1192                if (length != 0 && newStart [0] != newEnd [0]) {
1193                    TCHAR buffer = new TCHAR (getCodePage (), length + 1);
1194                    OS.GetWindowText (hwndText, buffer, length + 1);
1195                    newText = buffer.toString (newStart [0], newEnd [0] - newStart [0]);
1196                } else {
1197                    newText = "";
1198                }
1199                OS.CallWindowProc (EditProc, hwndText, msg, wParam, lParam);
1200                ignoreModify = false;
1201            }
1202            break;
1203    }
1204    if (newText != null) {
1205        String JavaDoc oldText = newText;
1206        newText = verifyText (newText, start [0], end [0], null);
1207        if (newText == null) return LRESULT.ZERO;
1208        if (!newText.equals (oldText)) {
1209            if (call) {
1210                OS.CallWindowProc (EditProc, hwndText, msg, wParam, lParam);
1211            }
1212            TCHAR buffer = new TCHAR (getCodePage (), newText, true);
1213            if (msg == OS.WM_SETTEXT) {
1214                int hHeap = OS.GetProcessHeap ();
1215                int byteCount = buffer.length () * TCHAR.sizeof;
1216                int pszText = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
1217                OS.MoveMemory (pszText, buffer, byteCount);
1218                int code = OS.CallWindowProc (EditProc, hwndText, msg, wParam, pszText);
1219                OS.HeapFree (hHeap, 0, pszText);
1220                return new LRESULT (code);
1221            } else {
1222                OS.SendMessage (hwndText, OS.EM_REPLACESEL, 0, buffer);
1223                return LRESULT.ZERO;
1224            }
1225        }
1226    }
1227    return null;
1228}
1229
1230LRESULT wmCommandChild (int wParam, int lParam) {
1231    int code = wParam >> 16;
1232    switch (code) {
1233        case OS.EN_CHANGE:
1234            if (ignoreModify) break;
1235            int value = getSelectionText ();
1236            if (value != -1) {
1237                int pos;
1238                if (OS.IsWinCE) {
1239                    pos = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0) & 0xFFFF;
1240                } else {
1241                    pos = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0);
1242                }
1243                if (pos != value) setSelection (value, true, false, true);
1244            }
1245            sendEvent (SWT.Modify);
1246            if (isDisposed ()) return LRESULT.ZERO;
1247            break;
1248    }
1249    return super.wmCommandChild (wParam, lParam);
1250}
1251
1252LRESULT wmKeyDown (int hwnd, int wParam, int lParam) {
1253    LRESULT result = super.wmKeyDown (hwnd, wParam, lParam);
1254    if (result != null) return result;
1255    
1256    /* Increment the value */
1257    UDACCEL udaccel = new UDACCEL ();
1258    OS.SendMessage (hwndUpDown, OS.UDM_GETACCEL, 1, udaccel);
1259    int delta = 0;
1260    switch (wParam) {
1261        case OS.VK_UP: delta = udaccel.nInc; break;
1262        case OS.VK_DOWN: delta = -udaccel.nInc; break;
1263        case OS.VK_PRIOR: delta = pageIncrement; break;
1264        case OS.VK_NEXT: delta = -pageIncrement; break;
1265    }
1266    if (delta != 0) {
1267        int value = getSelectionText ();
1268        if (value != -1) {
1269            if (OS.IsWinCE) {
1270                value = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0) & 0xFFFF;
1271            } else {
1272                value = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0);
1273            }
1274        }
1275        int newValue = value + delta;
1276        int [] max = new int [1], min = new int [1];
1277        OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, min, max);
1278        if ((style & SWT.WRAP) != 0) {
1279            if (newValue < min [0]) newValue = max [0];
1280            if (newValue > max [0]) newValue = min [0];
1281        }
1282        newValue = Math.min (Math.max (min [0], newValue), max [0]);
1283        if (value != newValue) setSelection (newValue, true, true, true);
1284    }
1285    
1286    /* Stop the edit control from moving the caret */
1287    switch (wParam) {
1288        case OS.VK_UP:
1289        case OS.VK_DOWN:
1290            return LRESULT.ZERO;
1291    }
1292    return result;
1293}
1294
1295LRESULT wmKillFocus (int hwnd, int wParam, int lParam) {
1296    int value = getSelectionText ();
1297    if (value == -1) {
1298        if (OS.IsWinCE) {
1299            value = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0) & 0xFFFF;
1300        } else {
1301            value = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0);
1302        }
1303        setSelection (value, false, true, false);
1304    }
1305    return super.wmKillFocus (hwnd, wParam, lParam);
1306}
1307
1308LRESULT wmNotifyChild (NMHDR hdr, int wParam, int lParam) {
1309    switch (hdr.code) {
1310        case OS.UDN_DELTAPOS:
1311            NMUPDOWN lpnmud = new NMUPDOWN ();
1312            OS.MoveMemory (lpnmud, lParam, NMUPDOWN.sizeof);
1313            int value = lpnmud.iPos + lpnmud.iDelta;
1314            int [] max = new int [1], min = new int [1];
1315            OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, min, max);
1316            if ((style & SWT.WRAP) != 0) {
1317                if (value < min [0]) value = max [0];
1318                if (value > max [0]) value = min [0];
1319            }
1320            /*
1321            * The SWT.Modify event is sent after the widget has been
1322            * updated with the new state. Rather than allowing
1323            * the default updown window proc to set the value
1324            * when the user clicks on the updown control, set
1325            * the value explicitly and stop the window proc
1326            * from running.
1327            */

1328            value = Math.min (Math.max (min [0], value), max [0]);
1329            if (value != lpnmud.iPos) {
1330                setSelection (value, true, true, true);
1331            }
1332            return LRESULT.ONE;
1333    }
1334    return super.wmNotifyChild (hdr, wParam, lParam);
1335}
1336
1337LRESULT wmScrollChild (int wParam, int lParam) {
1338    int code = wParam & 0xFFFF;
1339    switch (code) {
1340        case OS.SB_THUMBPOSITION:
1341            postEvent (SWT.Selection);
1342            break;
1343    }
1344    return super.wmScrollChild (wParam, lParam);
1345}
1346
1347}
1348
Popular Tags