]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Decorations.java
Remove invalid SHA-256-Digests
[simantics/platform.git] / bundles / org.eclipse.swt.win32.win32.x86_64 / src / org / eclipse / swt / widgets / Decorations.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2019 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.graphics.*;
19 import org.eclipse.swt.internal.*;
20 import org.eclipse.swt.internal.win32.*;
21
22 /**
23  * Instances of this class provide the appearance and
24  * behavior of <code>Shells</code>, but are not top
25  * level shells or dialogs. Class <code>Shell</code>
26  * shares a significant amount of code with this class,
27  * and is a subclass.
28  * <p>
29  * IMPORTANT: This class was intended to be abstract and
30  * should <em>never</em> be referenced or instantiated.
31  * Instead, the class <code>Shell</code> should be used.
32  * </p>
33  * <p>
34  * Instances are always displayed in one of the maximized,
35  * minimized or normal states:
36  * </p>
37  * <ul>
38  * <li>
39  * When an instance is marked as <em>maximized</em>, the
40  * window manager will typically resize it to fill the
41  * entire visible area of the display, and the instance
42  * is usually put in a state where it can not be resized
43  * (even if it has style <code>RESIZE</code>) until it is
44  * no longer maximized.
45  * </li><li>
46  * When an instance is in the <em>normal</em> state (neither
47  * maximized or minimized), its appearance is controlled by
48  * the style constants which were specified when it was created
49  * and the restrictions of the window manager (see below).
50  * </li><li>
51  * When an instance has been marked as <em>minimized</em>,
52  * its contents (client area) will usually not be visible,
53  * and depending on the window manager, it may be
54  * "iconified" (that is, replaced on the desktop by a small
55  * simplified representation of itself), relocated to a
56  * distinguished area of the screen, or hidden. Combinations
57  * of these changes are also possible.
58  * </li>
59  * </ul>
60  * Note: The styles supported by this class must be treated
61  * as <em>HINT</em>s, since the window manager for the
62  * desktop on which the instance is visible has ultimate
63  * control over the appearance and behavior of decorations.
64  * For example, some window managers only support resizable
65  * windows and will always assume the RESIZE style, even if
66  * it is not set.
67  * <dl>
68  * <dt><b>Styles:</b></dt>
69  * <dd>BORDER, CLOSE, MIN, MAX, NO_TRIM, RESIZE, TITLE, ON_TOP, TOOL</dd>
70  * <dt><b>Events:</b></dt>
71  * <dd>(none)</dd>
72  * </dl>
73  * Class <code>SWT</code> provides two "convenience constants"
74  * for the most commonly required style combinations:
75  * <dl>
76  * <dt><code>SHELL_TRIM</code></dt>
77  * <dd>
78  * the result of combining the constants which are required
79  * to produce a typical application top level shell: (that
80  * is, <code>CLOSE | TITLE | MIN | MAX | RESIZE</code>)
81  * </dd>
82  * <dt><code>DIALOG_TRIM</code></dt>
83  * <dd>
84  * the result of combining the constants which are required
85  * to produce a typical application dialog shell: (that
86  * is, <code>TITLE | CLOSE | BORDER</code>)
87  * </dd>
88  * </dl>
89  * <p>
90  * IMPORTANT: This class is intended to be subclassed <em>only</em>
91  * within the SWT implementation.
92  * </p>
93  *
94  * @see #getMinimized
95  * @see #getMaximized
96  * @see Shell
97  * @see SWT
98  * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
99  * @noextend This class is not intended to be subclassed by clients.
100  */
101 public class Decorations extends Canvas {
102         Image image, smallImage, largeImage;
103         Image [] images;
104         Menu menuBar;
105         Menu [] menus;
106         Control savedFocus;
107         Button defaultButton, saveDefault;
108         int swFlags, nAccel;
109         long hAccel;
110         boolean moved, resized, opened;
111         int oldX = OS.CW_USEDEFAULT, oldY = OS.CW_USEDEFAULT;
112         int oldWidth = OS.CW_USEDEFAULT, oldHeight = OS.CW_USEDEFAULT;
113         RECT maxRect = new RECT();
114
115 /**
116  * Prevents uninitialized instances from being created outside the package.
117  */
118 Decorations () {
119 }
120
121 /**
122  * Constructs a new instance of this class given its parent
123  * and a style value describing its behavior and appearance.
124  * <p>
125  * The style value is either one of the style constants defined in
126  * class <code>SWT</code> which is applicable to instances of this
127  * class, or must be built by <em>bitwise OR</em>'ing together
128  * (that is, using the <code>int</code> "|" operator) two or more
129  * of those <code>SWT</code> style constants. The class description
130  * lists the style constants that are applicable to the class.
131  * Style bits are also inherited from superclasses.
132  * </p>
133  *
134  * @param parent a composite control which will be the parent of the new instance (cannot be null)
135  * @param style the style of control to construct
136  *
137  * @exception IllegalArgumentException <ul>
138  *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
139  * </ul>
140  * @exception SWTException <ul>
141  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
142  *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
143  * </ul>
144  *
145  * @see SWT#BORDER
146  * @see SWT#CLOSE
147  * @see SWT#MIN
148  * @see SWT#MAX
149  * @see SWT#RESIZE
150  * @see SWT#TITLE
151  * @see SWT#NO_TRIM
152  * @see SWT#NO_MOVE
153  * @see SWT#SHELL_TRIM
154  * @see SWT#DIALOG_TRIM
155  * @see SWT#ON_TOP
156  * @see SWT#TOOL
157  * @see Widget#checkSubclass
158  * @see Widget#getStyle
159  */
160 public Decorations (Composite parent, int style) {
161         super (parent, checkStyle (style));
162 }
163
164 void _setMaximized (boolean maximized) {
165         swFlags = maximized ? OS.SW_SHOWMAXIMIZED : OS.SW_RESTORE;
166         if (!OS.IsWindowVisible (handle)) return;
167         if (maximized == OS.IsZoomed (handle)) return;
168         OS.ShowWindow (handle, swFlags);
169         OS.UpdateWindow (handle);
170 }
171
172 void _setMinimized (boolean minimized) {
173         swFlags = minimized ? OS.SW_SHOWMINNOACTIVE : OS.SW_RESTORE;
174         if (!OS.IsWindowVisible (handle)) return;
175         if (minimized == OS.IsIconic (handle)) return;
176         int flags = swFlags;
177         if (flags == OS.SW_SHOWMINNOACTIVE && handle == OS.GetActiveWindow ()) {
178                 flags = OS.SW_MINIMIZE;
179         }
180         OS.ShowWindow (handle, flags);
181         OS.UpdateWindow (handle);
182 }
183
184 void addMenu (Menu menu) {
185         if (menus == null) menus = new Menu [4];
186         for (int i=0; i<menus.length; i++) {
187                 if (menus [i] == null) {
188                         menus [i] = menu;
189                         return;
190                 }
191         }
192         Menu [] newMenus = new Menu [menus.length + 4];
193         newMenus [menus.length] = menu;
194         System.arraycopy (menus, 0, newMenus, 0, menus.length);
195         menus = newMenus;
196 }
197
198 void bringToTop () {
199         /*
200         * This code is intentionally commented.  On some platforms,
201         * the ON_TOP style creates a shell that will stay on top
202         * of every other shell on the desktop.  Using SetWindowPos ()
203         * with HWND_TOP caused problems on Windows 98 so this code is
204         * commented out until this functionality is specified and
205         * the problems are fixed.
206         */
207 //      if ((style & SWT.ON_TOP) != 0) {
208 //              int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE;
209 //              OS.SetWindowPos (handle, OS.HWND_TOP, 0, 0, 0, 0, flags);
210 //      } else {
211                 OS.BringWindowToTop (handle);
212                 // widget could be disposed at this point
213 //      }
214 }
215
216 static int checkStyle (int style) {
217         if ((style & SWT.NO_TRIM) != 0) {
218                 style &= ~(SWT.CLOSE | SWT.TITLE | SWT.MIN | SWT.MAX | SWT.RESIZE | SWT.BORDER);
219         } else if ((style & SWT.NO_MOVE) != 0) {
220                 style |= SWT.TITLE;
221         }
222         if ((style & (SWT.MENU | SWT.MIN | SWT.MAX | SWT.CLOSE)) != 0) {
223                 style |= SWT.TITLE;
224         }
225
226         /*
227         * If either WS_MINIMIZEBOX or WS_MAXIMIZEBOX are set,
228         * we must also set WS_SYSMENU or the buttons will not
229         * appear.
230         */
231         if ((style & (SWT.MIN | SWT.MAX)) != 0) style |= SWT.CLOSE;
232
233         /*
234         * Both WS_SYSMENU and WS_CAPTION must be set in order
235         * to for the system menu to appear.
236         */
237         if ((style & SWT.CLOSE) != 0) style |= SWT.TITLE;
238
239         /*
240         * Bug in Windows.  The WS_CAPTION style must be
241         * set when the window is resizable or it does not
242         * draw properly.
243         */
244         /*
245         * This code is intentionally commented.  It seems
246         * that this problem originally in Windows 3.11,
247         * has been fixed in later versions.  Because the
248         * exact nature of the drawing problem is unknown,
249         * keep the commented code around in case it comes
250         * back.
251         */
252 //      if ((style & SWT.RESIZE) != 0) style |= SWT.TITLE;
253
254         return style;
255 }
256
257 @Override
258 void checkBorder () {
259         /* Do nothing */
260 }
261
262 void checkComposited (Composite parent) {
263         /* Do nothing */
264 }
265
266 @Override
267 void checkOpened () {
268         if (!opened) resized = false;
269 }
270
271 @Override
272 protected void checkSubclass () {
273         if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
274 }
275
276 @Override
277 long callWindowProc (long hwnd, int msg, long wParam, long lParam) {
278         if (handle == 0) return 0;
279         return OS.DefMDIChildProc (hwnd, msg, wParam, lParam);
280 }
281
282 void closeWidget () {
283         Event event = new Event ();
284         sendEvent (SWT.Close, event);
285         if (event.doit && !isDisposed ()) dispose ();
286 }
287
288 int compare (ImageData data1, ImageData data2, int width, int height, int depth) {
289         int value1 = Math.abs (data1.width - width), value2 = Math.abs (data2.width - width);
290         if (value1 == value2) {
291                 int transparent1 = data1.getTransparencyType ();
292                 int transparent2 = data2.getTransparencyType ();
293                 if (transparent1 == transparent2) {
294                         if (data1.depth == data2.depth) return 0;
295                         return data1.depth > data2.depth && data1.depth <= depth ? -1 : 1;
296                 }
297                 if (transparent1 == SWT.TRANSPARENCY_ALPHA) return -1;
298                 if (transparent2 == SWT.TRANSPARENCY_ALPHA) return 1;
299                 if (transparent1 == SWT.TRANSPARENCY_MASK) return -1;
300                 if (transparent2 == SWT.TRANSPARENCY_MASK) return 1;
301                 if (transparent1 == SWT.TRANSPARENCY_PIXEL) return -1;
302                 if (transparent2 == SWT.TRANSPARENCY_PIXEL) return 1;
303                 return 0;
304         }
305         return value1 < value2 ? -1 : 1;
306 }
307
308 @Override
309 Widget computeTabGroup () {
310         return this;
311 }
312
313 @Override
314 Control computeTabRoot () {
315         return this;
316 }
317
318 @Override Rectangle computeTrimInPixels (int x, int y, int width, int height) {
319         checkWidget ();
320
321         /* Get the size of the trimmings */
322         RECT rect = new RECT ();
323         OS.SetRect (rect, x, y, x + width, y + height);
324         int bits1 = OS.GetWindowLong (handle, OS.GWL_STYLE);
325         int bits2 = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
326         boolean hasMenu = OS.GetMenu (handle) != 0;
327         OS.AdjustWindowRectEx (rect, bits1, hasMenu, bits2);
328
329         /* Get the size of the scroll bars */
330         if (horizontalBar != null) rect.bottom += OS.GetSystemMetrics (OS.SM_CYHSCROLL);
331         if (verticalBar != null) rect.right += OS.GetSystemMetrics (OS.SM_CXVSCROLL);
332
333         /* Compute the height of the menu bar */
334         if (hasMenu) {
335                 RECT testRect = new RECT ();
336                 OS.SetRect (testRect, 0, 0, rect.right - rect.left, rect.bottom - rect.top);
337                 OS.SendMessage (handle, OS.WM_NCCALCSIZE, 0, testRect);
338                 while ((testRect.bottom - testRect.top) < height) {
339                         if (testRect.bottom - testRect.top == 0) break;
340                         rect.top -= OS.GetSystemMetrics (OS.SM_CYMENU) - OS.GetSystemMetrics (OS.SM_CYBORDER);
341                         OS.SetRect (testRect, 0, 0, rect.right - rect.left, rect.bottom - rect.top);
342                         OS.SendMessage (handle, OS.WM_NCCALCSIZE, 0, testRect);
343                 }
344         }
345         return new Rectangle (rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
346 }
347
348 void createAccelerators () {
349         hAccel = nAccel = 0;
350         MenuItem [] items = display.items;
351         if (menuBar == null || items == null) {
352                 return;
353         }
354         ACCEL accel = new ACCEL ();
355         byte [] buffer1 = new byte [ACCEL.sizeof];
356         byte [] buffer2 = new byte [items.length * ACCEL.sizeof];
357         for (int i=0; i<items.length; i++) {
358                 MenuItem item = items [i];
359                 if (item != null && item.accelerator != 0) {
360                         Menu menu = item.parent;
361                         if (menu.parent == this) {
362                                 while (menu != null && menu != menuBar) {
363                                         menu = menu.getParentMenu ();
364                                 }
365                                 if (menu == menuBar && item.fillAccel (accel)) {
366                                         OS.MoveMemory (buffer1, accel, ACCEL.sizeof);
367                                         System.arraycopy (buffer1, 0, buffer2, nAccel * ACCEL.sizeof, ACCEL.sizeof);
368                                         nAccel++;
369                                 }
370                         }
371                 }
372         }
373         if (nAccel != 0) hAccel = OS.CreateAcceleratorTable (buffer2, nAccel);
374 }
375
376 @Override
377 void createHandle () {
378         super.createHandle ();
379         if (parent != null || ((style & SWT.TOOL) != 0)) {
380                 setParent ();
381                 setSystemMenu ();
382         }
383 }
384
385 @Override
386 void createWidget () {
387         super.createWidget ();
388         swFlags = OS.SW_SHOWNOACTIVATE;
389         hAccel = -1;
390 }
391
392 void destroyAccelerators () {
393         if (hAccel != 0 && hAccel != -1) OS.DestroyAcceleratorTable (hAccel);
394         hAccel = -1;
395 }
396
397 @Override
398 public void dispose () {
399         if (isDisposed()) return;
400         if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
401         if (!(this instanceof Shell)) {
402                 if (!traverseDecorations (true)) {
403                         Shell shell = getShell ();
404                         shell.setFocus ();
405                 }
406                 setVisible (false);
407         }
408         super.dispose ();
409 }
410
411 Menu findMenu (long hMenu) {
412         if (menus == null) return null;
413         for (int i=0; i<menus.length; i++) {
414                 Menu menu = menus [i];
415                 if (menu != null && hMenu == menu.handle) return menu;
416         }
417         return null;
418 }
419
420 void fixDecorations (Decorations newDecorations, Control control, Menu [] menus) {
421         if (this == newDecorations) return;
422         if (control == savedFocus) savedFocus = null;
423         if (control == defaultButton) defaultButton = null;
424         if (control == saveDefault) saveDefault = null;
425         if (menus == null) return;
426         Menu menu = control.menu;
427         if (menu != null) {
428                 int index = 0;
429                 while (index <menus.length) {
430                         if (menus [index] == menu) {
431                                 control.setMenu (null);
432                                 return;
433                         }
434                         index++;
435                 }
436                 menu.fixMenus (newDecorations);
437                 destroyAccelerators ();
438                 newDecorations.destroyAccelerators ();
439         }
440 }
441
442 @Override Rectangle getBoundsInPixels () {
443         checkWidget ();
444         if (OS.IsIconic (handle)) {
445                 WINDOWPLACEMENT lpwndpl = new WINDOWPLACEMENT ();
446                 lpwndpl.length = WINDOWPLACEMENT.sizeof;
447                 OS.GetWindowPlacement (handle, lpwndpl);
448                 if ((lpwndpl.flags & OS.WPF_RESTORETOMAXIMIZED) != 0) {
449                         int width = maxRect.right - maxRect.left;
450                         int height = maxRect.bottom - maxRect.top;
451                         return new Rectangle (maxRect.left, maxRect.top, width, height);
452                 }
453                 int width = lpwndpl.right - lpwndpl.left;
454                 int height = lpwndpl.bottom - lpwndpl.top;
455                 return new Rectangle (lpwndpl.left, lpwndpl.top, width, height);
456         }
457         return super.getBoundsInPixels ();
458 }
459
460 @Override Rectangle getClientAreaInPixels () {
461         checkWidget ();
462         if (OS.IsIconic (handle)) {
463                 WINDOWPLACEMENT lpwndpl = new WINDOWPLACEMENT ();
464                 lpwndpl.length = WINDOWPLACEMENT.sizeof;
465                 OS.GetWindowPlacement (handle, lpwndpl);
466                 if ((lpwndpl.flags & OS.WPF_RESTORETOMAXIMIZED) != 0) {
467                         return new Rectangle (0, 0, oldWidth, oldHeight);
468                 }
469                 int width = lpwndpl.right - lpwndpl.left;
470                 int height = lpwndpl.bottom - lpwndpl.top;
471                 /*
472                 * Feature in Windows.  For some reason WM_NCCALCSIZE does
473                 * not compute the client area when the window is minimized.
474                 * The fix is to compute it using AdjustWindowRectEx() and
475                 * GetSystemMetrics().
476                 *
477                 * NOTE: This code fails to compute the correct client area
478                 * for a minimized window where the menu bar would wrap were
479                 * the window restored.  There is no fix for this problem at
480                 * this time.
481                 */
482                 if (horizontalBar != null) width -= OS.GetSystemMetrics (OS.SM_CYHSCROLL);
483                 if (verticalBar != null) height -= OS.GetSystemMetrics (OS.SM_CXVSCROLL);
484                 RECT rect = new RECT ();
485                 int bits1 = OS.GetWindowLong (handle, OS.GWL_STYLE);
486                 int bits2 = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
487                 boolean hasMenu = OS.GetMenu (handle) != 0;
488                 OS.AdjustWindowRectEx (rect, bits1, hasMenu, bits2);
489                 width = Math.max (0, width - (rect.right - rect.left));
490                 height = Math.max (0, height - (rect.bottom - rect.top));
491                 return new Rectangle (0, 0, width, height);
492         }
493         return super.getClientAreaInPixels ();
494 }
495
496 /**
497  * Returns the receiver's default button if one had
498  * previously been set, otherwise returns null.
499  *
500  * @return the default button or null
501  *
502  * @exception SWTException <ul>
503  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
504  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
505  * </ul>
506  *
507  * @see #setDefaultButton(Button)
508  */
509 public Button getDefaultButton () {
510         checkWidget ();
511         if (defaultButton != null && defaultButton.isDisposed ()) return null;
512         return defaultButton;
513 }
514
515 /**
516  * Returns the receiver's image if it had previously been
517  * set using <code>setImage()</code>. The image is typically
518  * displayed by the window manager when the instance is
519  * marked as iconified, and may also be displayed somewhere
520  * in the trim when the instance is in normal or maximized
521  * states.
522  * <p>
523  * Note: This method will return null if called before
524  * <code>setImage()</code> is called. It does not provide
525  * access to a window manager provided, "default" image
526  * even if one exists.
527  * </p>
528  *
529  * @return the image
530  *
531  * @exception SWTException <ul>
532  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
533  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
534  * </ul>
535  */
536 public Image getImage () {
537         checkWidget ();
538         return image;
539 }
540
541 /**
542  * Returns the receiver's images if they had previously been
543  * set using <code>setImages()</code>. Images are typically
544  * displayed by the window manager when the instance is
545  * marked as iconified, and may also be displayed somewhere
546  * in the trim when the instance is in normal or maximized
547  * states. Depending where the icon is displayed, the platform
548  * chooses the icon with the "best" attributes.  It is expected
549  * that the array will contain the same icon rendered at different
550  * sizes, with different depth and transparency attributes.
551  *
552  * <p>
553  * Note: This method will return an empty array if called before
554  * <code>setImages()</code> is called. It does not provide
555  * access to a window manager provided, "default" image
556  * even if one exists.
557  * </p>
558  *
559  * @return the images
560  *
561  * @exception SWTException <ul>
562  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
563  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
564  * </ul>
565  *
566  * @since 3.0
567  */
568 public Image [] getImages () {
569         checkWidget ();
570         if (images == null) return new Image [0];
571         Image [] result = new Image [images.length];
572         System.arraycopy (images, 0, result, 0, images.length);
573         return result;
574 }
575
576 @Override Point getLocationInPixels () {
577         checkWidget ();
578         if (OS.IsIconic (handle)) {
579                 WINDOWPLACEMENT lpwndpl = new WINDOWPLACEMENT ();
580                 lpwndpl.length = WINDOWPLACEMENT.sizeof;
581                 OS.GetWindowPlacement (handle, lpwndpl);
582                 if ((lpwndpl.flags & OS.WPF_RESTORETOMAXIMIZED) != 0) {
583                         return new Point (maxRect.left, maxRect.top);
584                 }
585                 return new Point (lpwndpl.left, lpwndpl.top);
586         }
587         return super.getLocationInPixels ();
588 }
589
590 /**
591  * Returns <code>true</code> if the receiver is currently
592  * maximized, and false otherwise.
593  * <p>
594  *
595  * @return the maximized state
596  *
597  * @exception SWTException <ul>
598  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
599  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
600  * </ul>
601  *
602  * @see #setMaximized
603  */
604 public boolean getMaximized () {
605         checkWidget ();
606         if (OS.IsWindowVisible (handle)) return OS.IsZoomed (handle);
607         return swFlags == OS.SW_SHOWMAXIMIZED;
608 }
609
610 /**
611  * Returns the receiver's menu bar if one had previously
612  * been set, otherwise returns null.
613  *
614  * @return the menu bar or null
615  *
616  * @exception SWTException <ul>
617  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
618  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
619  * </ul>
620  */
621 public Menu getMenuBar () {
622         checkWidget ();
623         return menuBar;
624 }
625
626 /**
627  * Returns <code>true</code> if the receiver is currently
628  * minimized, and false otherwise.
629  * <p>
630  *
631  * @return the minimized state
632  *
633  * @exception SWTException <ul>
634  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
635  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
636  * </ul>
637  *
638  * @see #setMinimized
639  */
640 public boolean getMinimized () {
641         checkWidget ();
642         if (OS.IsWindowVisible (handle)) return OS.IsIconic (handle);
643         return swFlags == OS.SW_SHOWMINNOACTIVE;
644 }
645
646 @Override
647 String getNameText () {
648         return getText ();
649 }
650
651 @Override Point getSizeInPixels () {
652         checkWidget ();
653         if (OS.IsIconic (handle)) {
654                 WINDOWPLACEMENT lpwndpl = new WINDOWPLACEMENT ();
655                 lpwndpl.length = WINDOWPLACEMENT.sizeof;
656                 OS.GetWindowPlacement (handle, lpwndpl);
657                 if ((lpwndpl.flags & OS.WPF_RESTORETOMAXIMIZED) != 0) {
658                         int width = maxRect.right - maxRect.left;
659                         int height = maxRect.bottom - maxRect.top;
660                         return new Point (width, height);
661                 }
662                 int width = lpwndpl.right - lpwndpl.left;
663                 int height = lpwndpl.bottom - lpwndpl.top;
664                 return new Point (width, height);
665         }
666         return super.getSizeInPixels ();
667 }
668
669 /**
670  * Returns the receiver's text, which is the string that the
671  * window manager will typically display as the receiver's
672  * <em>title</em>. If the text has not previously been set,
673  * returns an empty string.
674  *
675  * @return the text
676  *
677  * @exception SWTException <ul>
678  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
679  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
680  * </ul>
681  */
682 public String getText () {
683         checkWidget ();
684         int length = OS.GetWindowTextLength (handle);
685         if (length == 0) return "";
686         char [] buffer = new char [length + 1];
687         OS.GetWindowText (handle, buffer, length + 1);
688         return new String (buffer, 0, length);
689 }
690
691 @Override
692 public boolean isReparentable () {
693         checkWidget ();
694         /*
695         * Feature in Windows.  Calling SetParent() for a shell causes
696         * a kind of fake MDI to happen.  It doesn't work well on Windows
697         * and is not supported on the other platforms.  The fix is to
698         * disallow the SetParent().
699         */
700         return false;
701 }
702
703 @Override
704 boolean isTabGroup () {
705         /*
706         * Can't test WS_TAB bits because they are the same as WS_MAXIMIZEBOX.
707         */
708         return true;
709 }
710
711 @Override
712 boolean isTabItem () {
713         /*
714         * Can't test WS_TAB bits because they are the same as WS_MAXIMIZEBOX.
715         */
716         return false;
717 }
718
719 @Override
720 Decorations menuShell () {
721         return this;
722 }
723
724 @Override
725 void releaseChildren (boolean destroy) {
726         if (menuBar != null) {
727                 menuBar.release (false);
728                 menuBar = null;
729         }
730         super.releaseChildren (destroy);
731         if (menus != null) {
732                 for (int i=0; i<menus.length; i++) {
733                         Menu menu = menus [i];
734                         if (menu != null && !menu.isDisposed ()) {
735                                 menu.dispose ();
736                         }
737                 }
738                 menus = null;
739         }
740 }
741
742 @Override
743 void releaseWidget () {
744         super.releaseWidget ();
745         if (smallImage != null) smallImage.dispose ();
746         if (largeImage != null) largeImage.dispose ();
747         smallImage = largeImage = image = null;
748         images = null;
749         savedFocus = null;
750         defaultButton = saveDefault = null;
751         if (hAccel != 0 && hAccel != -1) OS.DestroyAcceleratorTable (hAccel);
752         hAccel = -1;
753 }
754
755 void removeMenu (Menu menu) {
756         if (menus == null) return;
757         for (int i=0; i<menus.length; i++) {
758                 if (menus [i] == menu) {
759                         menus [i] = null;
760                         return;
761                 }
762         }
763 }
764
765 @Override
766 void reskinChildren (int flags) {
767         if (menuBar != null) menuBar.reskin (flags);
768         if (menus != null) {
769                 for (int i=0; i<menus.length; i++) {
770                         Menu menu = menus [i];
771                         if (menu != null) menu.reskin (flags);
772                 }
773         }
774         super.reskinChildren (flags);
775 }
776
777 boolean restoreFocus () {
778         if (display.ignoreRestoreFocus) return true;
779         if (savedFocus != null && savedFocus.isDisposed ()) savedFocus = null;
780         if (savedFocus != null && savedFocus.setFocus ()) return true;
781         return false;
782 }
783
784 void saveFocus () {
785         Control control = display._getFocusControl ();
786         if (control != null && control != this && this == control.menuShell ()) {
787                 setSavedFocus (control);
788         }
789 }
790
791 @Override
792 void setBoundsInPixels (int x, int y, int width, int height, int flags, boolean defer) {
793         swFlags = OS.SW_SHOWNOACTIVATE;
794         if (OS.IsIconic (handle)) {
795                 setPlacement (x, y, width, height, flags);
796                 return;
797         }
798         forceResize ();
799         RECT rect = new RECT ();
800         OS.GetWindowRect (handle, rect);
801         boolean sameOrigin = true;
802         if ((OS.SWP_NOMOVE & flags) == 0) {
803                 sameOrigin = rect.left == x && rect.top == y;
804                 if (!sameOrigin) moved = true;
805         }
806         boolean sameExtent = true;
807         if ((OS.SWP_NOSIZE & flags) == 0) {
808                 sameExtent = rect.right - rect.left == width && rect.bottom - rect.top == height;
809                 if (!sameExtent) resized = true;
810         }
811         if (OS.IsZoomed (handle)) {
812                 if (sameOrigin && sameExtent) return;
813                 setPlacement (x, y, width, height, flags);
814                 _setMaximized (false);
815                 return;
816         }
817         super.setBoundsInPixels (x, y, width, height, flags, defer);
818 }
819
820 /**
821  * If the argument is not null, sets the receiver's default
822  * button to the argument, and if the argument is null, sets
823  * the receiver's default button to the first button which
824  * was set as the receiver's default button (called the
825  * <em>saved default button</em>). If no default button had
826  * previously been set, or the saved default button was
827  * disposed, the receiver's default button will be set to
828  * null.
829  * <p>
830  * The default button is the button that is selected when
831  * the receiver is active and the user presses ENTER.
832  * </p>
833  *
834  * @param button the new default button
835  *
836  * @exception IllegalArgumentException <ul>
837  *    <li>ERROR_INVALID_ARGUMENT - if the button has been disposed</li>
838  *    <li>ERROR_INVALID_PARENT - if the control is not in the same widget tree</li>
839  * </ul>
840  * @exception SWTException <ul>
841  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
842  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
843  * </ul>
844  */
845 public void setDefaultButton (Button button) {
846         checkWidget ();
847         if (button != null) {
848                 if (button.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
849                 if (button.menuShell () != this) error(SWT.ERROR_INVALID_PARENT);
850         }
851         setDefaultButton (button, true);
852 }
853
854 void setDefaultButton (Button button, boolean save) {
855         if (button == null) {
856                 if (defaultButton == saveDefault) {
857                         if (save) saveDefault = null;
858                         return;
859                 }
860         } else {
861                 if ((button.style & SWT.PUSH) == 0) return;
862                 if (button == defaultButton) {
863                         if (save) saveDefault = defaultButton;
864                         return;
865                 }
866         }
867         if (defaultButton != null) {
868                 if (!defaultButton.isDisposed ()) defaultButton.setDefault (false);
869         }
870         if ((defaultButton = button) == null) defaultButton = saveDefault;
871         if (defaultButton != null) {
872                 if (!defaultButton.isDisposed ()) defaultButton.setDefault (true);
873         }
874         if (save) saveDefault = defaultButton;
875         if (saveDefault != null && saveDefault.isDisposed ()) saveDefault = null;
876 }
877
878 /**
879  * Sets the receiver's image to the argument, which may
880  * be null. The image is typically displayed by the window
881  * manager when the instance is marked as iconified, and
882  * may also be displayed somewhere in the trim when the
883  * instance is in normal or maximized states.
884  *
885  * @param image the new image (or null)
886  *
887  * @exception IllegalArgumentException <ul>
888  *    <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
889  * </ul>
890  * @exception SWTException <ul>
891  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
892  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
893  * </ul>
894  */
895 public void setImage (Image image) {
896         checkWidget ();
897         if (image != null && image.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
898         this.image = image;
899         setImages (image, null);
900 }
901
902 void setImages (Image image, Image [] images) {
903         if (smallImage != null) smallImage.dispose ();
904         if (largeImage != null) largeImage.dispose ();
905         smallImage = largeImage = null;
906         long hSmallIcon = 0, hLargeIcon = 0;
907         Image smallIcon = null, largeIcon = null;
908         if (image != null) {
909                 smallIcon = largeIcon = image;
910         } else {
911                 if (images != null && images.length > 0) {
912                         int depth = display.getIconDepth ();
913                         ImageData [] datas = null;
914                         if (images.length > 1) {
915                                 Image [] bestImages = new Image [images.length];
916                                 System.arraycopy (images, 0, bestImages, 0, images.length);
917                                 datas = new ImageData [images.length];
918                                 for (int i=0; i<datas.length; i++) {
919                                         datas [i] = images [i].getImageData (DPIUtil.getDeviceZoom ());
920                                 }
921                                 images = bestImages;
922                                 sort (images, datas, OS.GetSystemMetrics (OS.SM_CXSMICON), OS.GetSystemMetrics (OS.SM_CYSMICON), depth);
923                         }
924                         smallIcon = images [0];
925                         if (images.length > 1) {
926                                 sort (images, datas, OS.GetSystemMetrics (OS.SM_CXICON), OS.GetSystemMetrics (OS.SM_CYICON), depth);
927                         }
928                         largeIcon = images [0];
929                 }
930         }
931         if (smallIcon != null) {
932                 switch (smallIcon.type) {
933                         case SWT.BITMAP:
934                                 smallImage = Display.createIcon (smallIcon);
935                                 hSmallIcon = smallImage.handle;
936                                 break;
937                         case SWT.ICON:
938                                 hSmallIcon = smallIcon.handle;
939                                 break;
940                 }
941         }
942         OS.SendMessage (handle, OS.WM_SETICON, OS.ICON_SMALL, hSmallIcon);
943         if (largeIcon != null) {
944                 switch (largeIcon.type) {
945                         case SWT.BITMAP:
946                                 largeImage = Display.createIcon (largeIcon);
947                                 hLargeIcon = largeImage.handle;
948                                 break;
949                         case SWT.ICON:
950                                 hLargeIcon = largeIcon.handle;
951                                 break;
952                 }
953         }
954         OS.SendMessage (handle, OS.WM_SETICON, OS.ICON_BIG, hLargeIcon);
955
956         /*
957         * Bug in Windows.  When WM_SETICON is used to remove an
958         * icon from the window trimmings for a window with the
959         * extended style bits WS_EX_DLGMODALFRAME, the window
960         * trimmings do not redraw to hide the previous icon.
961         * The fix is to force a redraw.
962         */
963         if (hSmallIcon == 0 && hLargeIcon == 0 && (style & SWT.BORDER) != 0) {
964                 int flags = OS.RDW_FRAME | OS.RDW_INVALIDATE;
965                 OS.RedrawWindow (handle, null, 0, flags);
966         }
967 }
968
969 /**
970  * Sets the receiver's images to the argument, which may
971  * be an empty array. Images are typically displayed by the
972  * window manager when the instance is marked as iconified,
973  * and may also be displayed somewhere in the trim when the
974  * instance is in normal or maximized states. Depending where
975  * the icon is displayed, the platform chooses the icon with
976  * the "best" attributes. It is expected that the array will
977  * contain the same icon rendered at different sizes, with
978  * different depth and transparency attributes.
979  *
980  * @param images the new image array
981  *
982  * @exception IllegalArgumentException <ul>
983  *    <li>ERROR_NULL_ARGUMENT - if the array of images is null</li>
984  *    <li>ERROR_INVALID_ARGUMENT - if one of the images is null or has been disposed</li>
985  * </ul>
986  * @exception SWTException <ul>
987  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
988  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
989  * </ul>
990  *
991  * @since 3.0
992  */
993 public void setImages (Image [] images) {
994         checkWidget ();
995         if (images == null) error (SWT.ERROR_INVALID_ARGUMENT);
996         for (int i = 0; i < images.length; i++) {
997                 if (images [i] == null || images [i].isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
998         }
999         this.images = images;
1000         setImages (null, images);
1001 }
1002
1003 /**
1004  * Sets the maximized state of the receiver.
1005  * If the argument is <code>true</code> causes the receiver
1006  * to switch to the maximized state, and if the argument is
1007  * <code>false</code> and the receiver was previously maximized,
1008  * causes the receiver to switch back to either the minimized
1009  * or normal states.
1010  * <p>
1011  * Note: The result of intermixing calls to <code>setMaximized(true)</code>
1012  * and <code>setMinimized(true)</code> will vary by platform. Typically,
1013  * the behavior will match the platform user's expectations, but not
1014  * always. This should be avoided if possible.
1015  * </p>
1016  *
1017  * @param maximized the new maximized state
1018  *
1019  * @exception SWTException <ul>
1020  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1021  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1022  * </ul>
1023  *
1024  * @see #setMinimized
1025  */
1026 public void setMaximized (boolean maximized) {
1027         checkWidget ();
1028         Display.lpStartupInfo = null;
1029         _setMaximized (maximized);
1030 }
1031
1032 /**
1033  * Sets the receiver's menu bar to the argument, which
1034  * may be null.
1035  *
1036  * @param menu the new menu bar
1037  *
1038  * @exception IllegalArgumentException <ul>
1039  *    <li>ERROR_INVALID_ARGUMENT - if the menu has been disposed</li>
1040  *    <li>ERROR_INVALID_PARENT - if the menu is not in the same widget tree</li>
1041  * </ul>
1042  * @exception SWTException <ul>
1043  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1044  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1045  * </ul>
1046  */
1047 public void setMenuBar (Menu menu) {
1048         checkWidget ();
1049         if (menuBar == menu) return;
1050         if (menu != null) {
1051                 if (menu.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
1052                 if ((menu.style & SWT.BAR) == 0) error (SWT.ERROR_MENU_NOT_BAR);
1053                 if (menu.parent != this) error (SWT.ERROR_INVALID_PARENT);
1054         }
1055         if (menu != null) display.removeBar (menu);
1056         menuBar = menu;
1057         long hMenu = menuBar != null ? menuBar.handle: 0;
1058         OS.SetMenu (handle, hMenu);
1059         destroyAccelerators ();
1060 }
1061
1062 /**
1063  * Sets the minimized stated of the receiver.
1064  * If the argument is <code>true</code> causes the receiver
1065  * to switch to the minimized state, and if the argument is
1066  * <code>false</code> and the receiver was previously minimized,
1067  * causes the receiver to switch back to either the maximized
1068  * or normal states.
1069  * <p>
1070  * Note: The result of intermixing calls to <code>setMaximized(true)</code>
1071  * and <code>setMinimized(true)</code> will vary by platform. Typically,
1072  * the behavior will match the platform user's expectations, but not
1073  * always. This should be avoided if possible.
1074  * </p>
1075  *
1076  * @param minimized the new maximized state
1077  *
1078  * @exception SWTException <ul>
1079  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1080  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1081  * </ul>
1082  *
1083  * @see #setMaximized
1084  */
1085 public void setMinimized (boolean minimized) {
1086         checkWidget ();
1087         Display.lpStartupInfo = null;
1088         _setMinimized (minimized);
1089 }
1090
1091 @Override
1092 public void setOrientation (int orientation) {
1093         super.setOrientation (orientation);
1094         if (menus != null) {
1095                 for (int i=0; i<menus.length; i++) {
1096                         Menu menu = menus [i];
1097                         if (menu != null && !menu.isDisposed () && (menu.getStyle () & SWT.POP_UP) != 0) {
1098                                 menu._setOrientation (menu.getOrientation ());
1099                         }
1100                 }
1101         }
1102 }
1103
1104 void setParent () {
1105         /*
1106         * In order for an MDI child window to support
1107         * a menu bar, setParent () is needed to reset
1108         * the parent.  Otherwise, the MDI child window
1109         * will appear as a separate shell.  This is an
1110         * undocumented and possibly dangerous Windows
1111         * feature.
1112         */
1113         long hwndParent = parent.handle;
1114         display.lockActiveWindow = true;
1115         OS.SetParent (handle, hwndParent);
1116         if (!OS.IsWindowVisible (hwndParent)) {
1117                 OS.ShowWindow (handle, OS.SW_SHOWNA);
1118         }
1119         int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
1120         bits &= ~OS.WS_CHILD;
1121         OS.SetWindowLong (handle, OS.GWL_STYLE, bits | OS.WS_POPUP);
1122         OS.SetWindowLongPtr (handle, OS.GWLP_ID, 0);
1123         int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE;
1124         OS.SetWindowPos (handle, OS.HWND_BOTTOM, 0, 0, 0, 0, flags);
1125         display.lockActiveWindow = false;
1126 }
1127
1128 void setPlacement (int x, int y, int width, int height, int flags) {
1129         WINDOWPLACEMENT lpwndpl = new WINDOWPLACEMENT ();
1130         lpwndpl.length = WINDOWPLACEMENT.sizeof;
1131         OS.GetWindowPlacement (handle, lpwndpl);
1132         lpwndpl.showCmd = OS.SW_SHOWNA;
1133         if (OS.IsIconic (handle)) {
1134                 lpwndpl.showCmd = OS.SW_SHOWMINNOACTIVE;
1135         } else {
1136                 if (OS.IsZoomed (handle)) {
1137                         lpwndpl.showCmd = OS.SW_SHOWMAXIMIZED;
1138                 }
1139         }
1140         boolean sameOrigin = true;
1141         if ((flags & OS.SWP_NOMOVE) == 0) {
1142                 sameOrigin = lpwndpl.left != x || lpwndpl.top != y;
1143                 lpwndpl.right = x + (lpwndpl.right - lpwndpl.left);
1144                 lpwndpl.bottom = y + (lpwndpl.bottom - lpwndpl.top);
1145                 lpwndpl.left = x;
1146                 lpwndpl.top = y;
1147         }
1148         boolean sameExtent = true;
1149         if ((flags & OS.SWP_NOSIZE) == 0) {
1150                 sameExtent = lpwndpl.right - lpwndpl.left != width || lpwndpl.bottom - lpwndpl.top != height;
1151                 lpwndpl.right = lpwndpl.left + width;
1152                 lpwndpl.bottom = lpwndpl.top + height;
1153         }
1154         OS.SetWindowPlacement (handle, lpwndpl);
1155         if (OS.IsIconic (handle)) {
1156                 if (sameOrigin) {
1157                         moved = true;
1158                         Point location = getLocationInPixels ();
1159                         oldX = location.x;
1160                         oldY = location.y;
1161                         sendEvent (SWT.Move);
1162                         if (isDisposed ()) return;
1163                 }
1164                 if (sameExtent) {
1165                         resized = true;
1166                         Rectangle rect = getClientAreaInPixels ();
1167                         oldWidth = rect.width;
1168                         oldHeight = rect.height;
1169                         sendEvent (SWT.Resize);
1170                         if (isDisposed ()) return;
1171                         if (layout != null) {
1172                                 markLayout (false, false);
1173                                 updateLayout (true, false);
1174                         }
1175                 }
1176         }
1177 }
1178
1179 void setSavedFocus (Control control) {
1180         savedFocus = control;
1181 }
1182
1183 void setSystemMenu () {
1184         long hMenu = OS.GetSystemMenu (handle, false);
1185         if (hMenu == 0) return;
1186         int oldCount = OS.GetMenuItemCount (hMenu);
1187         if ((style & SWT.RESIZE) == 0) {
1188                 OS.DeleteMenu (hMenu, OS.SC_SIZE, OS.MF_BYCOMMAND);
1189         }
1190         if ((style & SWT.MIN) == 0) {
1191                 OS.DeleteMenu (hMenu, OS.SC_MINIMIZE, OS.MF_BYCOMMAND);
1192         }
1193         if ((style & SWT.MAX) == 0) {
1194                 OS.DeleteMenu (hMenu, OS.SC_MAXIMIZE, OS.MF_BYCOMMAND);
1195         }
1196         if ((style & (SWT.MIN | SWT.MAX)) == 0) {
1197                 OS.DeleteMenu (hMenu, OS.SC_RESTORE, OS.MF_BYCOMMAND);
1198         }
1199         int newCount = OS.GetMenuItemCount (hMenu);
1200         if ((style & SWT.CLOSE) == 0 || newCount != oldCount) {
1201                 OS.DeleteMenu (hMenu, OS.SC_TASKLIST, OS.MF_BYCOMMAND);
1202                 MENUITEMINFO info = new MENUITEMINFO ();
1203                 info.cbSize = MENUITEMINFO.sizeof;
1204                 info.fMask = OS.MIIM_ID;
1205                 int index = 0;
1206                 while (index < newCount) {
1207                         if (OS.GetMenuItemInfo (hMenu, index, true, info)) {
1208                                 if (info.wID == OS.SC_CLOSE) break;
1209                         }
1210                         index++;
1211                 }
1212                 if (index != newCount) {
1213                         OS.DeleteMenu (hMenu, index - 1, OS.MF_BYPOSITION);
1214                         if ((style & SWT.CLOSE) == 0) {
1215                                 OS.DeleteMenu (hMenu, OS.SC_CLOSE, OS.MF_BYCOMMAND);
1216                         }
1217                 }
1218         }
1219 }
1220
1221 /**
1222  * Sets the receiver's text, which is the string that the
1223  * window manager will typically display as the receiver's
1224  * <em>title</em>, to the argument, which must not be null.
1225  * <p>
1226  * Note: If control characters like '\n', '\t' etc. are used
1227  * in the string, then the behavior is platform dependent.
1228  * </p>
1229  *
1230  * @param string the new text
1231  *
1232  * @exception IllegalArgumentException <ul>
1233  *    <li>ERROR_NULL_ARGUMENT - if the text is null</li>
1234  * </ul>
1235  * @exception SWTException <ul>
1236  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1237  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1238  * </ul>
1239  */
1240 public void setText (String string) {
1241         checkWidget ();
1242         if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
1243         /* Use the character encoding for the default locale */
1244         TCHAR buffer = new TCHAR (0, string, true);
1245         /* Ensure that the title appears in the task bar.*/
1246         if ((state & FOREIGN_HANDLE) != 0) {
1247                 long hHeap = OS.GetProcessHeap ();
1248                 int byteCount = buffer.length () * TCHAR.sizeof;
1249                 long pszText = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
1250                 OS.MoveMemory (pszText, buffer, byteCount);
1251                 OS.DefWindowProc (handle, OS.WM_SETTEXT, 0, pszText);
1252                 if (pszText != 0) OS.HeapFree (hHeap, 0, pszText);
1253         } else {
1254                 OS.SetWindowText (handle, buffer);
1255         }
1256         if ((state & HAS_AUTO_DIRECTION) != 0) {
1257                 updateTextDirection (AUTO_TEXT_DIRECTION);
1258         }
1259 }
1260
1261 @Override
1262 public void setVisible (boolean visible) {
1263         checkWidget ();
1264         if (!getDrawing()) {
1265                 if (((state & HIDDEN) == 0) == visible) return;
1266         } else {
1267                 if (visible == OS.IsWindowVisible (handle)) return;
1268         }
1269         if (visible) {
1270                 /*
1271                 * It is possible (but unlikely), that application
1272                 * code could have disposed the widget in the show
1273                 * event.  If this happens, just return.
1274                 */
1275                 sendEvent (SWT.Show);
1276                 if (isDisposed ()) return;
1277                 if (!getDrawing()) {
1278                         state &= ~HIDDEN;
1279                 } else {
1280                         if (menuBar != null) {
1281                                 display.removeBar (menuBar);
1282                                 OS.DrawMenuBar (handle);
1283                         }
1284                         STARTUPINFO lpStartUpInfo = Display.lpStartupInfo;
1285                         if (lpStartUpInfo != null && (lpStartUpInfo.dwFlags & OS.STARTF_USESHOWWINDOW) != 0) {
1286                                 OS.ShowWindow (handle, lpStartUpInfo.wShowWindow);
1287                         } else {
1288                                 OS.ShowWindow (handle, swFlags);
1289                         }
1290                         if (isDisposed ()) return;
1291                         opened = true;
1292                         if (!moved) {
1293                                 moved = true;
1294                                 Point location = getLocationInPixels ();
1295                                 oldX = location.x;
1296                                 oldY = location.y;
1297                         }
1298                         if (!resized) {
1299                                 resized = true;
1300                                 Rectangle rect = getClientAreaInPixels ();
1301                                 oldWidth = rect.width;
1302                                 oldHeight = rect.height;
1303                         }
1304                         /*
1305                         * Bug in Windows.  On Vista using the Classic theme,
1306                         * when the window is hung and UpdateWindow() is called,
1307                         * nothing is drawn, and outstanding WM_PAINTs are cleared.
1308                         * This causes pixel corruption.  The fix is to avoid calling
1309                         * update on hung windows.
1310                         */
1311                         if (OS.IsAppThemed () || !OS.IsHungAppWindow (handle)) {
1312                                 OS.UpdateWindow (handle);
1313                         }
1314                 }
1315         } else {
1316                 if (OS.IsIconic (handle)) {
1317                         swFlags = OS.SW_SHOWMINNOACTIVE;
1318                 } else {
1319                         if (OS.IsZoomed (handle)) {
1320                                 swFlags = OS.SW_SHOWMAXIMIZED;
1321                         } else {
1322                                 swFlags = OS.SW_SHOWNOACTIVATE;
1323                         }
1324                 }
1325                 if (!getDrawing()) {
1326                         state |= HIDDEN;
1327                 } else {
1328                         OS.ShowWindow (handle, OS.SW_HIDE);
1329                 }
1330                 if (isDisposed ()) return;
1331                 sendEvent (SWT.Hide);
1332         }
1333 }
1334
1335 void sort (Image [] images, ImageData [] datas, int width, int height, int depth) {
1336         /* Shell Sort from K&R, pg 108 */
1337         int length = images.length;
1338         if (length <= 1) return;
1339         for (int gap=length/2; gap>0; gap/=2) {
1340                 for (int i=gap; i<length; i++) {
1341                         for (int j=i-gap; j>=0; j-=gap) {
1342                                 if (compare (datas [j], datas [j + gap], width, height, depth) >= 0) {
1343                                         Image swap = images [j];
1344                                         images [j] = images [j + gap];
1345                                         images [j + gap] = swap;
1346                                         ImageData swapData = datas [j];
1347                                         datas [j] = datas [j + gap];
1348                                         datas [j + gap] = swapData;
1349                                 }
1350                         }
1351                 }
1352         }
1353 }
1354
1355 @Override
1356 boolean translateAccelerator (MSG msg) {
1357         if (!isEnabled () || !isActive ()) return false;
1358         if (menuBar != null && !menuBar.isEnabled ()) return false;
1359         if (translateMDIAccelerator (msg) || translateMenuAccelerator (msg)) return true;
1360         Decorations decorations = parent.menuShell ();
1361         return decorations.translateAccelerator (msg);
1362 }
1363
1364 boolean translateMenuAccelerator (MSG msg) {
1365         if (hAccel == -1) createAccelerators ();
1366         return hAccel != 0 && OS.TranslateAccelerator (handle, hAccel, msg) != 0;
1367 }
1368
1369 boolean translateMDIAccelerator (MSG msg) {
1370         if (!(this instanceof Shell)) {
1371                 Shell shell = getShell ();
1372                 long hwndMDIClient = shell.hwndMDIClient;
1373                 if (hwndMDIClient != 0 && OS.TranslateMDISysAccel (hwndMDIClient, msg)) {
1374                         return true;
1375                 }
1376                 if (msg.message == OS.WM_KEYDOWN) {
1377                         if (OS.GetKeyState (OS.VK_CONTROL) >= 0) return false;
1378                         switch ((int)(msg.wParam)) {
1379                                 case OS.VK_F4:
1380                                         OS.PostMessage (handle, OS.WM_CLOSE, 0, 0);
1381                                         return true;
1382                                 case OS.VK_F6:
1383                                         if (traverseDecorations (true)) return true;
1384                         }
1385                         return false;
1386                 }
1387                 if (msg.message == OS.WM_SYSKEYDOWN) {
1388                         switch ((int)(msg.wParam)) {
1389                                 case OS.VK_F4:
1390                                         OS.PostMessage (shell.handle, OS.WM_CLOSE, 0, 0);
1391                                         return true;
1392                         }
1393                         return false;
1394                 }
1395         }
1396         return false;
1397 }
1398
1399 boolean traverseDecorations (boolean next) {
1400         Control [] children = parent._getChildren ();
1401         int length = children.length;
1402         int index = 0;
1403         while (index < length) {
1404                 if (children [index] == this) break;
1405                 index++;
1406         }
1407         /*
1408         * It is possible (but unlikely), that application
1409         * code could have disposed the widget in focus in
1410         * or out events.  Ensure that a disposed widget is
1411         * not accessed.
1412         */
1413         int start = index, offset = (next) ? 1 : -1;
1414         while ((index = (index + offset + length) % length) != start) {
1415                 Control child = children [index];
1416                 if (!child.isDisposed () && child instanceof Decorations) {
1417                         if (child.setFocus ()) return true;
1418                 }
1419         }
1420         return false;
1421 }
1422
1423 @Override
1424 boolean traverseItem (boolean next) {
1425         return false;
1426 }
1427
1428 @Override
1429 boolean traverseReturn () {
1430         if (defaultButton == null || defaultButton.isDisposed ()) return false;
1431         if (!defaultButton.isVisible () || !defaultButton.isEnabled ()) return false;
1432         defaultButton.click ();
1433         return true;
1434 }
1435
1436 @Override
1437 CREATESTRUCT widgetCreateStruct () {
1438         return new CREATESTRUCT ();
1439 }
1440
1441 @Override
1442 int widgetExtStyle () {
1443         int bits = super.widgetExtStyle () | OS.WS_EX_MDICHILD;
1444         bits &= ~OS.WS_EX_CLIENTEDGE;
1445         if ((style & SWT.NO_TRIM) != 0) return bits;
1446         if ((style & SWT.RESIZE) != 0) return bits;
1447         if ((style & SWT.BORDER) != 0) bits |= OS.WS_EX_DLGMODALFRAME;
1448         return bits;
1449 }
1450
1451 @Override
1452 long widgetParent () {
1453         Shell shell = getShell ();
1454         return shell.hwndMDIClient ();
1455 }
1456
1457 @Override
1458 int widgetStyle () {
1459         /*
1460         * Clear WS_VISIBLE and WS_TABSTOP.  NOTE: In Windows, WS_TABSTOP
1461         * has the same value as WS_MAXIMIZEBOX so these bits cannot be
1462         * used to control tabbing.
1463         */
1464         int bits = super.widgetStyle () & ~(OS.WS_TABSTOP | OS.WS_VISIBLE);
1465
1466         /* Set the title bits and no-trim bits */
1467         bits &= ~OS.WS_BORDER;
1468         if ((style & SWT.NO_TRIM) != 0) {
1469                 if (parent == null) {
1470                         bits |= OS.WS_SYSMENU | OS.WS_MINIMIZEBOX;
1471                 }
1472                 return bits;
1473         }
1474         if ((style & SWT.TITLE) != 0) bits |= OS.WS_CAPTION;
1475
1476         /* Set the min and max button bits */
1477         if ((style & SWT.MIN) != 0) bits |= OS.WS_MINIMIZEBOX;
1478         if ((style & SWT.MAX) != 0) bits |= OS.WS_MAXIMIZEBOX;
1479
1480         /* Set the resize, dialog border or border bits */
1481         if ((style & SWT.RESIZE) != 0) {
1482                 bits |= OS.WS_THICKFRAME;
1483         } else if ((style & SWT.BORDER) == 0) {
1484                 bits |= OS.WS_BORDER;
1485         }
1486
1487         /* Set the system menu and close box bits */
1488         if ((style & SWT.CLOSE) != 0) bits |= OS.WS_SYSMENU;
1489
1490         return bits;
1491 }
1492
1493 @Override
1494 long windowProc (long hwnd, int msg, long wParam, long lParam) {
1495         switch (msg) {
1496                 case Display.SWT_GETACCEL:
1497                 case Display.SWT_GETACCELCOUNT:
1498                         if (hAccel == -1) createAccelerators ();
1499                         return msg == Display.SWT_GETACCELCOUNT ? nAccel : hAccel;
1500         }
1501         return super.windowProc (hwnd, msg, wParam, lParam);
1502 }
1503
1504 @Override
1505 LRESULT WM_ACTIVATE (long wParam, long lParam) {
1506         LRESULT result = super.WM_ACTIVATE (wParam, lParam);
1507         if (result != null) return result;
1508         /*
1509         * Feature in AWT.  When an AWT Window is activated,
1510         * for some reason, it seems to forward the WM_ACTIVATE
1511         * message to the parent.  Normally, the parent is an
1512         * AWT Frame.  When AWT is embedded in SWT, the SWT
1513         * shell gets the WM_ACTIVATE and assumes that it came
1514         * from Windows.  When an SWT shell is activated it
1515         * restores focus to the last control that had focus.
1516         * If this control is an embedded composite, it takes
1517         * focus from the AWT Window.  The fix is to ignore
1518         * WM_ACTIVATE messages that come from AWT Windows.
1519         */
1520         if (OS.GetParent (lParam) == handle) {
1521                 char [] buffer = new char [128];
1522                 int length = OS.GetClassName (lParam, buffer, buffer.length);
1523                 String className = new String (buffer, 0, length);
1524                 if (className.equals (Display.AWT_WINDOW_CLASS)) {
1525                         return LRESULT.ZERO;
1526                 }
1527         }
1528         int loWord = OS.LOWORD (wParam);
1529         if (loWord != 0) {
1530                 /*
1531                 * When the high word of wParam is non-zero, the activation
1532                 * state of the window is being changed while the window is
1533                 * minimized. If this is the case, do not report activation
1534                 * events or restore the focus.
1535                 */
1536                 if (OS.HIWORD (wParam) != 0) return result;
1537                 Control control = display.findControl (lParam);
1538                 if (control == null || control instanceof Shell) {
1539                         if (this instanceof Shell) {
1540                                 Event event = new Event ();
1541                                 event.detail = loWord == OS.WA_CLICKACTIVE ? SWT.MouseDown : SWT.None;
1542                                 sendEvent (SWT.Activate, event);
1543                                 if (isDisposed ()) return LRESULT.ZERO;
1544                         }
1545                 }
1546                 if (restoreFocus ()) return LRESULT.ZERO;
1547         } else {
1548                 Display display = this.display;
1549                 boolean lockWindow = display.isXMouseActive ();
1550                 if (lockWindow) display.lockActiveWindow = true;
1551                 Control control = display.findControl (lParam);
1552                 if (control == null || control instanceof Shell) {
1553                         if (this instanceof Shell) {
1554                                 sendEvent (SWT.Deactivate);
1555                                 if (!isDisposed ()) {
1556                                         Shell shell = getShell ();
1557                                         shell.setActiveControl (null);
1558                                         // widget could be disposed at this point
1559                                 }
1560                         }
1561                 }
1562                 if (lockWindow) display.lockActiveWindow = false;
1563                 if (isDisposed ()) return LRESULT.ZERO;
1564                 saveFocus ();
1565         }
1566         return result;
1567 }
1568
1569 @Override
1570 LRESULT WM_CLOSE (long wParam, long lParam) {
1571         LRESULT result = super.WM_CLOSE (wParam, lParam);
1572         if (result != null) return result;
1573         if (isEnabled () && isActive ()) closeWidget ();
1574         return LRESULT.ZERO;
1575 }
1576
1577 @Override
1578 LRESULT WM_KILLFOCUS (long wParam, long lParam) {
1579         LRESULT result = super.WM_KILLFOCUS (wParam, lParam);
1580         saveFocus ();
1581         return result;
1582 }
1583
1584 @Override
1585 LRESULT WM_MOVE (long wParam, long lParam) {
1586         if (moved) {
1587                 Point location = getLocationInPixels ();
1588                 if (location.x == oldX && location.y == oldY) {
1589                         return null;
1590                 }
1591                 oldX = location.x;
1592                 oldY = location.y;
1593         }
1594         return super.WM_MOVE (wParam, lParam);
1595 }
1596
1597 @Override
1598 LRESULT WM_NCACTIVATE (long wParam, long lParam) {
1599         LRESULT result = super.WM_NCACTIVATE (wParam, lParam);
1600         if (result != null) return result;
1601         if (wParam == 0) {
1602                 if (display.lockActiveWindow) return LRESULT.ZERO;
1603                 Control control = display.findControl (lParam);
1604                 if (control != null) {
1605                         Shell shell = getShell ();
1606                         Decorations decorations = control.menuShell ();
1607                         if (decorations.getShell () == shell) {
1608                                 if (this instanceof Shell) return LRESULT.ONE;
1609                                 if (display.ignoreRestoreFocus) {
1610                                         if (display.lastHittest != OS.HTCLIENT) {
1611                                                 result = LRESULT.ONE;
1612                                         }
1613                                 }
1614                         }
1615                 }
1616         }
1617         if (!(this instanceof Shell)) {
1618                 long hwndShell = getShell().handle;
1619                 OS.SendMessage (hwndShell, OS.WM_NCACTIVATE, wParam, lParam);
1620         }
1621         return result;
1622 }
1623
1624 @Override
1625 LRESULT WM_QUERYOPEN (long wParam, long lParam) {
1626         LRESULT result = super.WM_QUERYOPEN (wParam, lParam);
1627         if (result != null) return result;
1628         sendEvent (SWT.Deiconify);
1629         // widget could be disposed at this point
1630         return result;
1631 }
1632
1633 @Override
1634 LRESULT WM_SETFOCUS (long wParam, long lParam) {
1635         LRESULT result = super.WM_SETFOCUS (wParam, lParam);
1636         if (isDisposed ()) return result;
1637         if (savedFocus != this) restoreFocus ();
1638         return result;
1639 }
1640
1641 @Override
1642 LRESULT WM_SIZE (long wParam, long lParam) {
1643         LRESULT result = null;
1644         boolean changed = true;
1645         if (resized) {
1646                 int newWidth = 0, newHeight = 0;
1647                 switch ((int)wParam) {
1648                         case OS.SIZE_MAXIMIZED:
1649                                 OS.GetWindowRect (handle, maxRect);
1650                         case OS.SIZE_RESTORED:
1651                                 newWidth = OS.LOWORD (lParam);
1652                                 newHeight = OS.HIWORD (lParam);
1653                                 break;
1654                         case OS.SIZE_MINIMIZED:
1655                                 Rectangle rect = getClientAreaInPixels ();
1656                                 newWidth = rect.width;
1657                                 newHeight = rect.height;
1658                                 break;
1659                 }
1660                 changed = newWidth != oldWidth || newHeight != oldHeight;
1661                 if (changed) {
1662                         oldWidth = newWidth;
1663                         oldHeight = newHeight;
1664                 }
1665         }
1666         if (changed) {
1667                 result = super.WM_SIZE (wParam, lParam);
1668                 if (isDisposed ()) return result;
1669         }
1670         if (wParam == OS.SIZE_MINIMIZED) {
1671                 sendEvent (SWT.Iconify);
1672                 // widget could be disposed at this point
1673         }
1674         return result;
1675 }
1676
1677 @Override
1678 LRESULT WM_SYSCOMMAND (long wParam, long lParam) {
1679         LRESULT result = super.WM_SYSCOMMAND (wParam, lParam);
1680         if (result != null) return result;
1681         if (!(this instanceof Shell)) {
1682                 int cmd = (int)wParam & 0xFFF0;
1683                 switch (cmd) {
1684                         case OS.SC_CLOSE: {
1685                                 OS.PostMessage (handle, OS.WM_CLOSE, 0, 0);
1686                                 return LRESULT.ZERO;
1687                         }
1688                         case OS.SC_NEXTWINDOW: {
1689                                 traverseDecorations (true);
1690                                 return LRESULT.ZERO;
1691                         }
1692                 }
1693         }
1694         return result;
1695 }
1696
1697 @Override
1698 LRESULT WM_WINDOWPOSCHANGING (long wParam, long lParam) {
1699         LRESULT result = super.WM_WINDOWPOSCHANGING (wParam, lParam);
1700         if (result != null) return result;
1701         if (display.lockActiveWindow) {
1702                 WINDOWPOS lpwp = new WINDOWPOS ();
1703                 OS.MoveMemory (lpwp, lParam, WINDOWPOS.sizeof);
1704                 lpwp.flags |= OS.SWP_NOZORDER;
1705                 OS.MoveMemory (lParam, lpwp, WINDOWPOS.sizeof);
1706         }
1707         return result;
1708 }
1709
1710 }