changeset 213:36f5cb12e1a2

Update to SWT 3.4M7
author Frank Benoit <benoit@tionex.de>
date Sat, 17 May 2008 17:34:28 +0200
parents ab60f3309436
children a8fed3e56433
files dwt/DWT.d dwt/accessibility/Accessible.d dwt/custom/CCombo.d dwt/custom/CLabel.d dwt/custom/CTabFolder.d dwt/custom/CTabItem.d dwt/custom/LineBackgroundEvent.d dwt/custom/LineStyleEvent.d dwt/custom/SashForm.d dwt/custom/ScrolledComposite.d dwt/custom/StyleRange.d dwt/custom/StyledText.d dwt/custom/StyledTextDropTargetEffect.d dwt/custom/StyledTextPrintOptions.d dwt/custom/StyledTextRenderer.d dwt/custom/TableCursor.d dwt/custom/TableTreeItem.d dwt/dnd/Clipboard.d dwt/dnd/DND.d dwt/dnd/DragSource.d dwt/dnd/DropTarget.d dwt/dnd/DropTargetEffect.d dwt/dnd/HTMLTransfer.d dwt/dnd/ImageTransfer.d dwt/dnd/OleEnumFORMATETC.d dwt/dnd/TableDragSourceEffect.d dwt/dnd/TreeDragSourceEffect.d dwt/dnd/TreeDropTargetEffect.d dwt/dnd/URLTransfer.d dwt/graphics/Color.d dwt/graphics/Cursor.d dwt/graphics/Device.d dwt/graphics/Font.d dwt/graphics/GC.d dwt/graphics/GCData.d dwt/graphics/Image.d dwt/graphics/ImageData.d dwt/graphics/Path.d dwt/graphics/Pattern.d dwt/graphics/Region.d dwt/graphics/Resource.d dwt/graphics/TextLayout.d dwt/graphics/TextStyle.d dwt/graphics/Transform.d dwt/internal/BidiUtil.d dwt/internal/Compatibility.d dwt/internal/ImageList.d dwt/internal/Library.d dwt/internal/gdip/Gdip.d dwt/internal/image/FileFormat.d dwt/internal/image/GIFFileFormat.d dwt/internal/image/JPEGAppn.d dwt/internal/image/JPEGArithmeticConditioningTable.d dwt/internal/image/JPEGComment.d dwt/internal/image/JPEGDecoder.d dwt/internal/image/JPEGEndOfImage.d dwt/internal/image/JPEGFileFormat.d dwt/internal/image/JPEGFixedSizeSegment.d dwt/internal/image/JPEGFrameHeader.d dwt/internal/image/JPEGHuffmanTable.d dwt/internal/image/JPEGQuantizationTable.d dwt/internal/image/JPEGRestartInterval.d dwt/internal/image/JPEGScanHeader.d dwt/internal/image/JPEGStartOfImage.d dwt/internal/image/LEDataInputStream.d dwt/internal/image/LEDataOutputStream.d dwt/internal/image/LZWCodec.d dwt/internal/image/OS2BMPFileFormat.d dwt/internal/image/PNGFileFormat.d dwt/internal/image/PngChunk.d dwt/internal/image/PngDecodingDataStream.d dwt/internal/image/PngDeflater.d dwt/internal/image/PngEncoder.d dwt/internal/image/PngHuffmanTable.d dwt/internal/image/PngIdatChunk.d dwt/internal/image/PngIhdrChunk.d dwt/internal/image/PngInputStream.d dwt/internal/image/PngPlteChunk.d dwt/internal/image/PngTrnsChunk.d dwt/internal/image/TIFFDirectory.d dwt/internal/image/TIFFFileFormat.d dwt/internal/image/WinBMPFileFormat.d dwt/internal/image/WinICOFileFormat.d dwt/internal/ole/win32/COM.d dwt/internal/ole/win32/COMAPI.d dwt/internal/win32/OS.d dwt/internal/win32/WINAPI.d dwt/internal/win32/WINTYPES.d dwt/layout/RowLayout.d dwt/printing/PrintDialog.d dwt/printing/Printer.d dwt/printing/PrinterData.d dwt/program/Program.d dwt/widgets/Button.d dwt/widgets/Canvas.d dwt/widgets/Caret.d dwt/widgets/ColorDialog.d dwt/widgets/Combo.d dwt/widgets/Composite.d dwt/widgets/Control.d dwt/widgets/CoolBar.d dwt/widgets/DateTime.d dwt/widgets/Decorations.d dwt/widgets/Dialog.d dwt/widgets/DirectoryDialog.d dwt/widgets/Display.d dwt/widgets/Event.d dwt/widgets/EventTable.d dwt/widgets/ExpandBar.d dwt/widgets/FileDialog.d dwt/widgets/FontDialog.d dwt/widgets/Group.d dwt/widgets/IME.d dwt/widgets/Label.d dwt/widgets/Link.d dwt/widgets/List.d dwt/widgets/Menu.d dwt/widgets/MenuItem.d dwt/widgets/MessageBox.d dwt/widgets/Monitor.d dwt/widgets/ProgressBar.d dwt/widgets/Sash.d dwt/widgets/Scale.d dwt/widgets/ScrollBar.d dwt/widgets/Scrollable.d dwt/widgets/Shell.d dwt/widgets/Slider.d dwt/widgets/Spinner.d dwt/widgets/Synchronizer.d dwt/widgets/TabFolder.d dwt/widgets/TabItem.d dwt/widgets/Table.d dwt/widgets/TableColumn.d dwt/widgets/TableItem.d dwt/widgets/Text.d dwt/widgets/ToolBar.d dwt/widgets/ToolItem.d dwt/widgets/ToolTip.d dwt/widgets/Tracker.d dwt/widgets/Tree.d dwt/widgets/TreeColumn.d dwt/widgets/TreeItem.d dwt/widgets/Widget.d
diffstat 143 files changed, 10289 insertions(+), 4019 deletions(-) [+]
line wrap: on
line diff
--- a/dwt/DWT.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/DWT.d	Sat May 17 17:34:28 2008 +0200
@@ -640,9 +640,76 @@
      */
     public static const int PaintItem = 42;
 
+    /**
+     * The IME composition event type (value is 43).
+     * <p>
+     * The IME composition event is sent to allow
+     * custom text editors to implement in-line
+     * editing of international text.
+     * </p>
+     *
+     * The detail field indicates the action to be taken:
+     * <p><ul>
+     * <li>{@link DWT#COMPOSITION_CHANGED}</li>
+     * <li>{@link DWT#COMPOSITION_OFFSET}</li>
+     * <li>{@link DWT#COMPOSITION_SELECTION}</li>
+     * </ul></p>
+     *
+     * @see dwt.widgets.Widget#addListener
+     * @see dwt.widgets.Display#addFilter
+     * @see dwt.widgets.Event
+     *
+     * @since 3.4
+     */
+    public static const int ImeComposition = 43;
+
     /* Event Details */
 
     /**
+     * The IME composition event detail that indicates
+     * a change in the IME composition. The text field
+     * of the event is the new composition text.
+     * The start and end indicate the offsets where the
+     * composition text should be inserted.
+     * The styles and ranges are stored in the IME
+     * object (value is 1).
+     *
+     * @see DWT#ImeComposition
+     *
+     * @since 3.4
+     */
+    public static const int COMPOSITION_CHANGED = 1;
+
+    /**
+     * The IME composition event detail that indicates
+     * that the IME needs the offset for a given location.
+     * The x and y fields of the event are used by the
+     * application to determine the offset.
+     *
+     * The index field of the event should be set to the
+     * text offset at that location. The count field should
+     * be set to indicate whether the location is closer to
+     * the leading edge (0) or the trailing edge (1) (value is 2).
+     *
+     * @see DWT#ImeComposition
+     * @see dwt.graphics.TextLayout#getOffset(int, int, int[])
+     *
+     * @since 3.4
+     */
+    public static const int COMPOSITION_OFFSET = 2;
+
+    /**
+     * The IME composition event detail that indicates
+     * that IME needs the selected text and its start
+     * and end offsets (value is 3).
+     *
+     * @see DWT#ImeComposition
+     *
+     * @since 3.4
+     */
+    public static const int COMPOSITION_SELECTION = 3;
+
+    /**
      * Indicates that a user-interface component is being dragged,
      * for example dragging the thumb of a scroll bar (value is 1).
      */
@@ -1135,6 +1202,23 @@
     public static const int V_SCROLL = 1 << 9;
 
     /**
+     * Style constant for no scrollbar behavior (value is 1&lt;&lt;4).
+     * <p>
+     * When neither H_SCROLL or V_SCROLL are specified, controls
+     * are free to create the default scroll bars for the control.
+     * Using NO_SCROLL overrides the default and forces the control
+     * to have no scroll bars.
+     *
+     * <b>Used By:</b><ul>
+     * <li><code>Tree</code></li>
+     * <li><code>Table</code></li>
+     * </ul></p>
+     *
+     * @since 3.4
+     */
+    public static const int NO_SCROLL = 1 << 4;
+
+    /**
      * Style constant for bordered behavior (value is 1&lt;&lt;11).
      * <br>Note that this is a <em>HINT</em>.
      * <p><b>Used By:</b><ul>
@@ -1289,7 +1373,15 @@
 
     /**
      * Style constant for no focus from the mouse behavior (value is 1&lt;&lt;19).
+     * <p>
+     * Normally, when the user clicks on a control, focus is assigned to that
+     * control, providing the control has no children.  Some controls, such as
+     * tool bars and sashes, don't normally take focus when the mouse is clicked
+     * or accept focus when assigned from within the program.  This style allows
+     * Composites to implement "no focus" mouse behavior.
+     *
      * <br>Note that this is a <em>HINT</em>.
+     * </p>
      * <p><b>Used By:</b><ul>
      * <li><code>Composite</code></li>
      * </ul></p>
@@ -1304,6 +1396,8 @@
      * the DWT.Paint event is not sent. When it gets bigger, an DWT.Paint event is
      * sent with a GC clipped to only the new areas to be painted. Without this
      * style, the entire client area will be repainted.
+     *
+     * <br>Note that this is a <em>HINT</em>.
      * </p><p><b>Used By:</b><ul>
      * <li><code>Composite</code></li>
      * </ul></p>
@@ -1312,6 +1406,8 @@
 
     /**
      * Style constant for no paint event merging behavior (value is 1&lt;&lt;21).
+     *
+     * <br>Note that this is a <em>HINT</em>.
      * <p><b>Used By:</b><ul>
      * <li><code>Composite</code></li>
      * </ul></p>
@@ -1409,16 +1505,104 @@
     public static const int DOUBLE_BUFFERED = 1 << 29;
 
     /**
+     * Style constant for transparent behavior (value is 1&lt;&lt;30).
+     * <p>
+     * By default, before a widget paints, the client area is filled with the current background.
+     * When this style is specified, the background is not filled and widgets that are obscured
+     * will draw through.
+     * </p><p><b>Used By:</b><ul>
+     * <li><code>Composite</code></li>
+     * </ul></p>
+     *
+     * @since 3.4
+     *
+     * WARNING: THIS API IS UNDER CONSTRUCTION AND SHOULD NOT BE USED
+     */
+    public static const int TRANSPARENT = 1 << 30;
+
+    /**
      * Style constant for align up behavior (value is 1&lt;&lt;7,
      * since align UP and align TOP are considered the same).
      * <p><b>Used By:</b><ul>
      * <li><code>Button</code> with <code>ARROW</code> style</li>
      * <li><code>Tracker</code></li>
+     * <li><code>Table</code></li>
+     * <li><code>Tree</code></li>
      * </ul></p>
      */
     public static const int UP = 1 << 7;
 
     /**
+     * Style constant to indicate single underline (value is 0).
+     * <p><b>Used By:</b><ul>
+     * <li><code>TextStyle</code></li>
+     * </ul></p>
+     *
+     * @since 3.4
+     */
+    public static const int UNDERLINE_SINGLE = 0;
+
+    /**
+     * Style constant to indicate double underline (value is 1).
+     * <p><b>Used By:</b><ul>
+     * <li><code>TextStyle</code></li>
+     * </ul></p>
+     *
+     * @since 3.4
+     */
+    public static const int UNDERLINE_DOUBLE = 1;
+
+    /**
+     * Style constant to indicate error underline (value is 2).
+     * <p><b>Used By:</b><ul>
+     * <li><code>TextStyle</code></li>
+     * </ul></p>
+     *
+     * @since 3.4
+     */
+    public static const int UNDERLINE_ERROR = 2;
+
+    /**
+     * Style constant to indicate squiggle underline (value is 3).
+     * <p><b>Used By:</b><ul>
+     * <li><code>TextStyle</code></li>
+     * </ul></p>
+     *
+     * @since 3.4
+     */
+    public static const int UNDERLINE_SQUIGGLE = 3;
+
+    /**
+     * Style constant to indicate solid border (value is 1).
+     * <p><b>Used By:</b><ul>
+     * <li><code>TextStyle</code></li>
+     * </ul></p>
+     *
+     * @since 3.4
+     */
+    public static const int BORDER_SOLID = 1;
+
+    /**
+     * Style constant to indicate dashed border (value is 2).
+     * <p><b>Used By:</b><ul>
+     * <li><code>TextStyle</code></li>
+     * </ul></p>
+     *
+     * @since 3.4
+     */
+    public static const int BORDER_DASH = 2;
+
+    /**
+     * Style constant to indicate dotted border (value is 4).
+     * <p><b>Used By:</b><ul>
+     * <li><code>TextStyle</code></li>
+     * </ul></p>
+     *
+     * @since 3.4
+     */
+    public static const int BORDER_DOT = 4;
+
+    /**
      * Style constant for align top behavior (value is 1&lt;&lt;7,
      * since align UP and align TOP are considered the same).
      * <p><b>Used By:</b><ul>
@@ -1433,6 +1617,8 @@
      * <p><b>Used By:</b><ul>
      * <li><code>Button</code> with <code>ARROW</code> style</li>
      * <li><code>Tracker</code></li>
+     * <li><code>Table</code></li>
+     * <li><code>Tree</code></li>
      * </ul></p>
      */
     public static const int DOWN               = 1 << 10;
@@ -2950,8 +3136,32 @@
     public static const int IMAGE_GRAY = 2;
 
     /**
+     * Constant to indicate an error state (value is 1).
+     * <p><b>Used By:</b><ul>
+     * <li><code>ProgressBar</code></li>
+     * </ul></p>
+     *
+     * @since 3.4
+     */
+    public static const int ERROR = 1;
+
+    /**
+     * Constant to a indicate a paused state (value is 4).
+     * <p><b>Used By:</b><ul>
+     * <li><code>ProgressBar</code></li>
+     * </ul></p>
+     *
+     * @since 3.4
+     */
+    public static const int PAUSED = 1 << 2;
+
+    /**
      * The font style constant indicating a normal weight, non-italic font
-     * (value is 0).
+     * (value is 0). This constant is also used with <code>ProgressBar</code>
+     * to indicate a normal state.
+     * <p><b>Used By:</b><ul>
+     * <li><code>ProgressBar</code></li>
+     * </ul></p>
      */
     public static const int NORMAL = 0;
 
--- a/dwt/accessibility/Accessible.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/accessibility/Accessible.d	Sat May 17 17:34:28 2008 +0200
@@ -257,7 +257,7 @@
      */
     public int /*long*/ internal_WM_GETOBJECT (int /*long*/ wParam, int /*long*/ lParam) {
         if (objIAccessible is null) return 0;
-        if (cast(int)/*64*/lParam is COM.OBJID_CLIENT) {
+        if (lParam is COM.OBJID_CLIENT) {
             /* LresultFromObject([in] riid, [in] wParam, [in] pAcc)
              * The argument pAcc is owned by the caller so reference count does not
              * need to be incremented.
@@ -511,6 +511,7 @@
         if (childID is ACC.CHILDID_NONE) {
             return iaccessible.accHitTest(xLeft, yTop, pvarChild);
         }
+        //TODO - use VARIANT structure
         pvarChild.vt = COM.VT_I4;
         pvarChild.lVal = childIDToOs(childID);
         return COM.S_OK;
@@ -537,7 +538,7 @@
         }
 
         AccessibleControlEvent event = new AccessibleControlEvent(this);
-        event.childID = osToChildID(cast(int)/*64*/v.lVal);
+        event.childID = osToChildID(v.lVal);
         event.x = osLeft;
         event.y = osTop;
         event.width = osWidth;
@@ -585,7 +586,7 @@
         }
 
         AccessibleControlEvent event = new AccessibleControlEvent(this);
-        event.childID = osToChildID(cast(int)/*64*/v.lVal);
+        event.childID = osToChildID(v.lVal);
         for (int i = 0; i < accessibleControlListeners.length; i++) {
             AccessibleControlListener listener = cast(AccessibleControlListener) accessibleControlListeners[i];
             listener.getChild(event);
@@ -640,7 +641,7 @@
         }
 
         AccessibleControlEvent event = new AccessibleControlEvent(this);
-        event.childID = osToChildID(cast(int)/*64*/v.lVal);
+        event.childID = osToChildID(v.lVal);
         event.result = osDefaultAction;
         for (int i = 0; i < accessibleControlListeners.length; i++) {
             AccessibleControlListener listener = cast(AccessibleControlListener) accessibleControlListeners[i];
@@ -673,7 +674,7 @@
         }
 
         AccessibleEvent event = new AccessibleEvent(this);
-        event.childID = osToChildID(cast(int)/*64*/v.lVal);
+        event.childID = osToChildID(v.lVal);
         event.result = osDescription;
 
         // TEMPORARY CODE
@@ -724,6 +725,7 @@
         int code = iaccessible.get_accFocus(pvarChild);
         if (accessibleControlListeners.length is 0) return code;
         if (code is COM.S_OK) {
+            //TODO - use VARIANT structure
             short[1] pvt;
             COM.MoveMemory(pvt.ptr, pvarChild, 2);
             if (pvt[0] is COM.VT_I4) {
@@ -779,7 +781,7 @@
         }
 
         AccessibleEvent event = new AccessibleEvent(this);
-        event.childID = osToChildID(cast(int)/*64*/v.lVal);
+        event.childID = osToChildID(v.lVal);
         event.result = osHelp;
         for (int i = 0; i < accessibleListeners.length; i++) {
             AccessibleListener listener = cast(AccessibleListener) accessibleListeners[i];
@@ -816,7 +818,7 @@
         }
 
         AccessibleEvent event = new AccessibleEvent(this);
-        event.childID = osToChildID(cast(int)/*64*/v.lVal);
+        event.childID = osToChildID(v.lVal);
         event.result = osKeyboardShortcut;
         for (int i = 0; i < accessibleListeners.length; i++) {
             AccessibleListener listener = cast(AccessibleListener) accessibleListeners[i];
@@ -845,7 +847,7 @@
         }
 
         AccessibleEvent event = new AccessibleEvent(this);
-        event.childID = osToChildID(cast(int)/*64*/v.lVal);
+        event.childID = osToChildID(v.lVal);
         event.result = osName;
         for (int i = 0; i < accessibleListeners.length; i++) {
             AccessibleListener listener = cast(AccessibleListener) accessibleListeners[i];
@@ -880,6 +882,7 @@
         // TEMPORARY CODE - process tree and table even if there are no apps listening
         if (accessibleControlListeners.length is 0 && !( null !is cast(Tree)control || null !is cast(Table)control )) return code;
         if (code is COM.S_OK) {
+            //TODO - use VARIANT structure
             short[1] pvt;
             COM.MoveMemory(pvt.ptr, pvarRole, 2);
             if (pvt[0] is COM.VT_I4) {
@@ -890,7 +893,7 @@
         }
 
         AccessibleControlEvent event = new AccessibleControlEvent(this);
-        event.childID = osToChildID(cast(int)/*64*/v.lVal);
+        event.childID = osToChildID(v.lVal);
         event.detail = osToRole(osRole);
         // TEMPORARY CODE
         /* Currently our checkbox table and tree are emulated using state mask
@@ -922,6 +925,7 @@
         int code = iaccessible.get_accSelection(pvarChildren);
         if (accessibleControlListeners.length is 0) return code;
         if (code is COM.S_OK) {
+            //TODO - use VARIANT structure
             short[1] pvt;
             COM.MoveMemory(pvt.ptr, pvarChildren, 2);
             if (pvt[0] is COM.VT_I4) {
@@ -982,6 +986,7 @@
         // TEMPORARY CODE - process tree and table even if there are no apps listening
         if (accessibleControlListeners.length is 0 && !( null !is cast(Tree)control || null !is cast(Table)control )) return code;
         if (code is COM.S_OK) {
+            //TODO - use VARIANT structure
             short[1] pvt;
             COM.MoveMemory(pvt.ptr, pvarState, 2);
             if (pvt[0] is COM.VT_I4) {
@@ -990,9 +995,9 @@
                 osState = pState[0];
             }
         }
-
+        bool grayed = false;
         AccessibleControlEvent event = new AccessibleControlEvent(this);
-        event.childID = osToChildID(cast(int)/*64*/v.lVal);
+        event.childID = osToChildID(v.lVal);
         event.detail = osToState(osState);
         // TEMPORARY CODE
         /* Currently our checkbox table and tree are emulated using state mask
@@ -1011,11 +1016,14 @@
                 auto result = OS.SendMessage (hwnd, OS.TVM_GETITEM, 0, &tvItem);
                 bool checked = (result !is 0) && (((tvItem.state >> 12) & 1) is 0);
                 if (checked) event.detail |= ACC.STATE_CHECKED;
+                grayed = tvItem.state >> 12 > 2;
             } else if (null !is cast(Table)control && (control.getStyle() & DWT.CHECK) !is 0) {
                 Table table = cast(Table) control;
-                TableItem item = table.getItem(event.childID);
-                if (item !is null) {
+                int index = event.childID;
+                if (0 <= index && index < table.getItemCount()) {
+                    TableItem item = table.getItem(index);
                     if (item.getChecked()) event.detail |= ACC.STATE_CHECKED;
+                    if (item.getGrayed()) grayed = true;
                 }
             }
         }
@@ -1024,6 +1032,10 @@
             listener.getState(event);
         }
         int state = stateToOs(event.detail);
+        if ((state & ACC.STATE_CHECKED) !is 0 && grayed) {
+            state &= ~ COM.STATE_SYSTEM_CHECKED;
+            state |= COM.STATE_SYSTEM_MIXED;
+        }
         pvarState.vt = COM.VT_I4;
         pvarState.lVal = state;
         return COM.S_OK;
@@ -1048,7 +1060,7 @@
         }
 
         AccessibleControlEvent event = new AccessibleControlEvent(this);
-        event.childID = osToChildID(cast(int)/*64*/v.lVal);
+        event.childID = osToChildID(v.lVal);
         event.result = osValue;
         for (int i = 0; i < accessibleControlListeners.length; i++) {
             AccessibleControlListener listener = cast(AccessibleControlListener) accessibleControlListeners[i];
@@ -1140,6 +1152,7 @@
                     int item = val.value;
                     rgvar[i].vt = COM.VT_I4;
                     rgvar[i].byRef = cast(void*)item;
+                    COM.MoveMemory(rgvar + i * VARIANT.sizeof + 8, &item, 4);
                 } else {
                     Accessible accessible = cast(Accessible) nextItem;
                     accessible.AddRef();
@@ -1189,7 +1202,7 @@
          */
         if (accessibleControlListeners.length is 0) {
             IEnumVARIANT ienumvariant;
-            int code = cast(int)/*64*/iaccessible.QueryInterface(&COM.IIDIEnumVARIANT, cast(void**)&ienumvariant);
+            int code = iaccessible.QueryInterface(&COM.IIDIEnumVARIANT, cast(void**)&ienumvariant);
             if (code !is COM.S_OK) return code;
             code = ienumvariant.Reset();
             ienumvariant.Release();
@@ -1215,7 +1228,7 @@
             IEnumVARIANT[1] pEnum;
             code = ienumvariant.Clone(pEnum.ptr);
             ienumvariant.Release();
-            COM.MoveMemory(ppEnum, pEnum.ptr, 4);
+            COM.MoveMemory(ppEnum, pEnum.ptr, (void*).sizeof);
             return code;
         }
 
@@ -1236,7 +1249,7 @@
         */
         if (!(cast(Tree)control )) return childID + 1;
         if (OS.COMCTL32_MAJOR < 6) return childID;
-        return cast(int)/*64*/OS.SendMessage (control.handle, OS.TVM_MAPHTREEITEMTOACCID, childID, 0);
+        return OS.SendMessage (control.handle, OS.TVM_MAPHTREEITEMTOACCID, childID, 0);
     }
 
     int osToChildID(int osChildID) {
@@ -1250,7 +1263,7 @@
         */
         if (!(cast(Tree)control )) return osChildID - 1;
         if (OS.COMCTL32_MAJOR < 6) return osChildID;
-        return cast(int)/*64*/OS.SendMessage (control.handle, OS.TVM_MAPACCIDTOHTREEITEM, osChildID, 0);
+        return OS.SendMessage (control.handle, OS.TVM_MAPACCIDTOHTREEITEM, osChildID, 0);
     }
 
     int stateToOs(int state) {
--- a/dwt/custom/CCombo.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/custom/CCombo.d	Sat May 17 17:34:28 2008 +0200
@@ -51,6 +51,7 @@
 static import tango.text.Unicode;
 static import tango.text.convert.Format;
 import dwt.dwthelper.utils;
+import dwt.dwthelper.Runnable;
 
 /**
  * The CCombo class represents a selectable user interface object
@@ -152,7 +153,12 @@
                 return;
             }
             if (getShell () is event.widget) {
-                handleFocus (DWT.FocusOut);
+                getDisplay().asyncExec(new class() Runnable {
+                    public void run() {
+                        if (isDisposed()) return;
+                        handleFocus (DWT.FocusOut);
+                    }
+                });
             }
         }
     };
@@ -165,13 +171,13 @@
         }
     };
 
-    int [] comboEvents = [DWT.Dispose, DWT.Move, DWT.Resize];
+    int [] comboEvents = [DWT.Dispose, DWT.FocusIn, DWT.Move, DWT.Resize];
     for (int i=0; i<comboEvents.length; i++) this.addListener (comboEvents [i], listener);
 
-    int [] textEvents = [DWT.KeyDown, DWT.KeyUp, DWT.MenuDetect, DWT.Modify, DWT.MouseDown, DWT.MouseUp, DWT.Traverse, DWT.FocusIn, DWT.Verify];
+    int [] textEvents = [DWT.DefaultSelection, DWT.KeyDown, DWT.KeyUp, DWT.MenuDetect, DWT.Modify, DWT.MouseDown, DWT.MouseUp, DWT.MouseDoubleClick, DWT.MouseWheel, DWT.Traverse, DWT.FocusIn, DWT.Verify];
     for (int i=0; i<textEvents.length; i++) text.addListener (textEvents [i], listener);
 
-    int [] arrowEvents = [DWT.Selection, DWT.FocusIn];
+    int [] arrowEvents = [DWT.MouseDown, DWT.MouseUp, DWT.Selection, DWT.FocusIn];
     for (int i=0; i<arrowEvents.length; i++) arrow.addListener (arrowEvents [i], listener);
 
     createPopup(null, -1);
@@ -179,7 +185,7 @@
 }
 static int checkStyle (int style) {
     int mask = DWT.BORDER | DWT.READ_ONLY | DWT.FLAT | DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT;
-    return style & mask;
+    return DWT.NO_FOCUS | (style & mask);
 }
 /**
  * Adds the argument to the end of the receiver's list.
@@ -318,7 +324,30 @@
             handleFocus (DWT.FocusIn);
             break;
         }
+        case DWT.MouseDown: {
+            Event mouseEvent = new Event ();
+            mouseEvent.button = event.button;
+            mouseEvent.count = event.count;
+            mouseEvent.stateMask = event.stateMask;
+            mouseEvent.time = event.time;
+            mouseEvent.x = event.x; mouseEvent.y = event.y;
+            notifyListeners (DWT.MouseDown, mouseEvent);
+            event.doit = mouseEvent.doit;
+            break;
+        }
+        case DWT.MouseUp: {
+            Event mouseEvent = new Event ();
+            mouseEvent.button = event.button;
+            mouseEvent.count = event.count;
+            mouseEvent.stateMask = event.stateMask;
+            mouseEvent.time = event.time;
+            mouseEvent.x = event.x; mouseEvent.y = event.y;
+            notifyListeners (DWT.MouseUp, mouseEvent);
+            event.doit = mouseEvent.doit;
+            break;
+        }
         case DWT.Selection: {
+            text.setFocus();
             dropDown (!isDropped ());
             break;
         }
@@ -363,6 +392,15 @@
             list = null;
             arrow = null;
             break;
+        case DWT.FocusIn:
+            Control focusControl = getDisplay ().getFocusControl ();
+            if (focusControl is arrow || focusControl is list) return;
+            if (isDropped()) {
+                list.setFocus();
+            } else {
+                text.setFocus();
+            }
+            break;
         case DWT.Move:
             dropDown (false);
             break;
@@ -465,7 +503,12 @@
  */
 public void deselect (int index) {
     checkWidget ();
-    list.deselect (index);
+    if (0 <= index && index < list.getItemCount () &&
+            index is list.getSelectionIndex() &&
+            text.getText().equals(list.getItem(index))) {
+        text.setText("");  //$NON-NLS-1$
+        list.deselect (index);
+    }
 }
 /**
  * Deselects all selected items in the receiver's list.
@@ -483,13 +526,14 @@
  */
 public void deselectAll () {
     checkWidget ();
+    text.setText("");  //$NON-NLS-1$
     list.deselectAll ();
 }
 void dropDown (bool drop) {
     if (drop is isDropped ()) return;
     if (!drop) {
         popup.setVisible (false);
-        if (!isDisposed ()&& arrow.isFocusControl()) {
+        if (!isDisposed () && isFocusControl()) {
             text.setFocus();
         }
         return;
@@ -527,7 +571,7 @@
     if (x + width > displayRect.x + displayRect.width) x = displayRect.x + displayRect.width - listRect.width;
     popup.setBounds (x, y, width, height);
     popup.setVisible (true);
-    list.setFocus ();
+    if (isFocusControl()) list.setFocus ();
 }
 /*
  * Return the lowercase of the first non-'&' character following
@@ -655,6 +699,29 @@
     checkWidget ();
     return list.getItems ();
 }
+/**
+ * Returns <code>true</code> if the receiver's list is visible,
+ * and <code>false</code> otherwise.
+ * <p>
+ * If one of the receiver's ancestors is not visible or some
+ * other condition makes the receiver not visible, this method
+ * may still indicate that it is considered visible even though
+ * it may not actually be showing.
+ * </p>
+ *
+ * @return the receiver's list's visibility state
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @since 3.4
+ */
+public bool getListVisible () {
+    checkWidget ();
+    return isDropped();
+}
 public override Menu getMenu() {
     return text.getMenu();
 }
@@ -905,7 +972,7 @@
 
         public void getLocation (AccessibleControlEvent e) {
             Rectangle location = getBounds ();
-            Point pt = toDisplay (location.x, location.y);
+            Point pt = getParent().toDisplay (location.x, location.y);
             e.x = pt.x;
             e.y = pt.y;
             e.width = location.width;
@@ -1002,6 +1069,12 @@
                 case DWT.TRAVERSE_ARROW_NEXT:
                     event.doit = false;
                     break;
+                case DWT.TRAVERSE_TAB_NEXT:
+                case DWT.TRAVERSE_TAB_PREVIOUS:
+                    event.doit = text.traverse(event.detail);
+                    event.detail = DWT.TRAVERSE_NONE;
+                    if (event.doit) dropDown(false);
+                    return;
                 default:
             }
             Event e = new Event ();
@@ -1093,8 +1166,10 @@
              * we hide the popup in the deactivate event, the selection event will show
              * it again. To prevent the popup from showing again, we will let the selection
              * event of the arrow button hide the popup.
+             * In Windows, hiding the popup during the deactivate causes the deactivate
+             * to be called twice and the selection event to be disappear.
              */
-            if ("gtk".equals(DWT.getPlatform())) {
+            if (!"carbon".equals(DWT.getPlatform())) {
                 Point point = arrow.toControl(getDisplay().getCursorLocation());
                 Point size = arrow.getSize();
                 Rectangle rect = new Rectangle(0, 0, size.x, size.y);
@@ -1317,6 +1392,7 @@
 }
 public override bool setFocus () {
     checkWidget();
+    if (!isEnabled () || !isVisible ()) return false;
     if (isFocusControl ()) return true;
     return text.setFocus ();
 }
@@ -1394,6 +1470,28 @@
     checkWidget ();
     return;
 }
+/**
+ * Marks the receiver's list as visible if the argument is <code>true</code>,
+ * and marks it invisible otherwise.
+ * <p>
+ * If one of the receiver's ancestors is not visible or some
+ * other condition makes the receiver not visible, marking
+ * it visible may not actually cause it to be displayed.
+ * </p>
+ *
+ * @param visible the new visibility state
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @since 3.4
+ */
+public void setListVisible (bool visible) {
+    checkWidget ();
+    dropDown(visible);
+}
 public override void setMenu(Menu menu) {
     text.setMenu(menu);
 }
@@ -1526,6 +1624,14 @@
             handleFocus (DWT.FocusIn);
             break;
         }
+        case DWT.DefaultSelection: {
+            dropDown (false);
+            Event e = new Event ();
+            e.time = event.time;
+            e.stateMask = event.stateMask;
+            notifyListeners (DWT.DefaultSelection, e);
+            break;
+        }
         case DWT.KeyDown: {
             Event keyEvent = new Event ();
             keyEvent.time = event.time;
@@ -1536,16 +1642,6 @@
             if (isDisposed ()) break;
             event.doit = keyEvent.doit;
             if (!event.doit) break;
-
-            if (event.character is DWT.CR) {
-                dropDown (false);
-                Event selectionEvent = new Event ();
-                selectionEvent.time = event.time;
-                selectionEvent.stateMask = event.stateMask;
-                notifyListeners (DWT.DefaultSelection, selectionEvent);
-                if (isDisposed ()) break;
-            }
-
             if (event.keyCode is DWT.ARROW_UP || event.keyCode is DWT.ARROW_DOWN) {
                 event.doit = false;
                 if ((event.stateMask & DWT.ALT) !is 0) {
@@ -1599,6 +1695,16 @@
             break;
         }
         case DWT.MouseDown: {
+            Event mouseEvent = new Event ();
+            mouseEvent.button = event.button;
+            mouseEvent.count = event.count;
+            mouseEvent.stateMask = event.stateMask;
+            mouseEvent.time = event.time;
+            mouseEvent.x = event.x; mouseEvent.y = event.y;
+            notifyListeners (DWT.MouseDown, mouseEvent);
+            if (isDisposed ()) break;
+            event.doit = mouseEvent.doit;
+            if (!event.doit) break;
             if (event.button !is 1) return;
             if (text.getEditable ()) return;
             bool dropped = isDropped ();
@@ -1608,14 +1714,60 @@
             break;
         }
         case DWT.MouseUp: {
+            Event mouseEvent = new Event ();
+            mouseEvent.button = event.button;
+            mouseEvent.count = event.count;
+            mouseEvent.stateMask = event.stateMask;
+            mouseEvent.time = event.time;
+            mouseEvent.x = event.x; mouseEvent.y = event.y;
+            notifyListeners (DWT.MouseUp, mouseEvent);
+            if (isDisposed ()) break;
+            event.doit = mouseEvent.doit;
+            if (!event.doit) break;
             if (event.button !is 1) return;
             if (text.getEditable ()) return;
             text.selectAll ();
             break;
         }
+        case DWT.MouseDoubleClick: {
+            Event mouseEvent = new Event ();
+            mouseEvent.button = event.button;
+            mouseEvent.count = event.count;
+            mouseEvent.stateMask = event.stateMask;
+            mouseEvent.time = event.time;
+            mouseEvent.x = event.x; mouseEvent.y = event.y;
+            notifyListeners (DWT.MouseDoubleClick, mouseEvent);
+            break;
+        }
+        case DWT.MouseWheel: {
+            Event keyEvent = new Event ();
+            keyEvent.time = event.time;
+            keyEvent.keyCode = event.count > 0 ? DWT.ARROW_UP : DWT.ARROW_DOWN;
+            keyEvent.stateMask = event.stateMask;
+            notifyListeners (DWT.KeyDown, keyEvent);
+            if (isDisposed ()) break;
+            event.doit = keyEvent.doit;
+            if (!event.doit) break;
+            if (event.count !is 0) {
+                event.doit = false;
+                int oldIndex = getSelectionIndex ();
+                if (event.count > 0) {
+                    select (Math.max (oldIndex - 1, 0));
+                } else {
+                    select (Math.min (oldIndex + 1, getItemCount () - 1));
+                }
+                if (oldIndex !is getSelectionIndex ()) {
+                    Event e = new Event();
+                    e.time = event.time;
+                    e.stateMask = event.stateMask;
+                    notifyListeners (DWT.Selection, e);
+                }
+                if (isDisposed ()) break;
+            }
+            break;
+        }
         case DWT.Traverse: {
             switch (event.detail) {
-                case DWT.TRAVERSE_RETURN:
                 case DWT.TRAVERSE_ARROW_PREVIOUS:
                 case DWT.TRAVERSE_ARROW_NEXT:
                     // The enter causes default selection and
@@ -1623,9 +1775,12 @@
                     // do not use them for traversal.
                     event.doit = false;
                     break;
+                case DWT.TRAVERSE_TAB_PREVIOUS:
+                    event.doit = traverse(DWT.TRAVERSE_TAB_PREVIOUS);
+                    event.detail = DWT.TRAVERSE_NONE;
+                    return;
                 default:
             }
-
             Event e = new Event ();
             e.time = event.time;
             e.detail = event.detail;
--- a/dwt/custom/CLabel.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/custom/CLabel.d	Sat May 17 17:34:28 2008 +0200
@@ -33,6 +33,7 @@
 import dwt.graphics.Image;
 import dwt.graphics.Point;
 import dwt.graphics.Rectangle;
+import dwt.graphics.TextLayout;
 import dwt.widgets.Canvas;
 import dwt.widgets.Composite;
 import dwt.widgets.Control;
@@ -797,25 +798,33 @@
     int min = 0;
     int mid = (max+min)/2 - 1;
     if (mid <= 0) return t;
+    TextLayout layout = new TextLayout (getDisplay());
+    layout.setText(t);
+    mid = validateOffset(layout, mid);
     while (min < mid && mid < max) {
         String s1 = t[0 .. mid].dup;
-        String s2 = t[l-mid .. l].dup;
+        String s2 = t.substring(validateOffset(layout, l-mid), l);
         int l1 = gc.textExtent(s1, DRAW_FLAGS).x;
         int l2 = gc.textExtent(s2, DRAW_FLAGS).x;
         if (l1+w+l2 > width) {
             max = mid;
-            mid = (max+min)/2;
+            mid = validateOffset(layout, (max+min)/2);
         } else if (l1+w+l2 < width) {
             min = mid;
-            mid = (max+min)/2;
+            mid = validateOffset(layout, (max+min)/2);
         } else {
             min = max;
         }
     }
-    if (mid is 0) return t;
-    return t[ 0 .. mid ] ~ ELLIPSIS ~ t[ l-mid .. l ];
+    String result = mid is 0 ? t : t.substring(0, mid) ~ ELLIPSIS ~ t.substring(validateOffset(layout, l-mid), l);
+    layout.dispose();
+    return result;
 }
-
+int validateOffset(TextLayout layout, int offset) {
+    int nextOffset = layout.getNextOffset(offset, DWT.MOVEMENT_CLUSTER);
+    if (nextOffset !is offset) return layout.getPreviousOffset(nextOffset, DWT.MOVEMENT_CLUSTER);
+    return offset;
+}
 private String[] splitString(String text) {
     String[] lines = new String[1];
     int start = 0, pos;
--- a/dwt/custom/CTabFolder.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/custom/CTabFolder.d	Sat May 17 17:34:28 2008 +0200
@@ -1538,6 +1538,8 @@
     style &= ~(DWT.SINGLE | DWT.MULTI);
     style |= single ? DWT.SINGLE : DWT.MULTI;
     if (borderLeft !is 0) style |= DWT.BORDER;
+    style &= ~DWT.CLOSE;
+    if (showClose) style |= DWT.CLOSE;
     return style;
 }
 /**
@@ -1712,20 +1714,26 @@
 
         public void getLocation(AccessibleControlEvent e) {
             Rectangle location = null;
+            Point pt = null;
             int childID = e.childID;
             if (childID is ACC.CHILDID_SELF) {
                 location = getBounds();
-            } else if (childID >= 0 && childID < items.length) {
-                location = items[childID].getBounds();
-            } else if (showChevron && childID is items.length + CHEVRON_CHILD_ID) {
-                location = chevronRect;
-            } else if (showMin && childID is items.length + MINIMIZE_CHILD_ID) {
-                location = minRect;
-            } else if (showMax && childID is items.length + MAXIMIZE_CHILD_ID) {
-                location = maxRect;
+                pt = getParent().toDisplay(location.x, location.y);
+            } else {
+                if (childID >= 0 && childID < items.length && items[childID].isShowing()) {
+                    location = items[childID].getBounds();
+                } else if (showChevron && childID is items.length + CHEVRON_CHILD_ID) {
+                    location = chevronRect;
+                } else if (showMin && childID is items.length + MINIMIZE_CHILD_ID) {
+                    location = minRect;
+                } else if (showMax && childID is items.length + MAXIMIZE_CHILD_ID) {
+                    location = maxRect;
+                }
+                if (location !is null) {
+                    pt = toDisplay(location.x, location.y);
+                }
             }
-            if (location !is null) {
-                Point pt = toDisplay(location.x, location.y);
+            if (location !is null && pt !is null) {
                 e.x = pt.x;
                 e.y = pt.y;
                 e.width = location.width;
@@ -2217,8 +2225,8 @@
                         CTabFolderListener listener = tabListeners[j];
                         listener.itemClosed(e);
                     }
-                    if (e.doit) {
-                        item.dispose();
+                    if (e.doit) item.dispose();
+                    if (!isDisposed() && item.isDisposed()) {
                         Display display = getDisplay();
                         Point pt = display.getCursorLocation();
                         pt = display.map(null, this, pt.x, pt.y);
@@ -3261,16 +3269,19 @@
     selection.closeImageState = NORMAL;
     selection.showing = false;
 
-    Control control = selection.control;
-    if (control !is null && !control.isDisposed()) {
-        control.setBounds(getClientArea());
-        control.setVisible(true);
+    Control newControl = selection.control;
+    Control oldControl = null;
+    if (oldIndex !is -1) {
+        oldControl = items[oldIndex].control;
     }
 
-    if (oldIndex !is -1) {
-        control = items[oldIndex].control;
-        if (control !is null && !control.isDisposed()) {
-            control.setVisible(false);
+    if (newControl !is oldControl) {
+        if (newControl !is null && !newControl.isDisposed()) {
+            newControl.setBounds(getClientArea());
+            newControl.setVisible(true);
+        }
+        if (oldControl !is null && !oldControl.isDisposed()) {
+            oldControl.setVisible(false);
         }
     }
     showItem(selection);
--- a/dwt/custom/CTabItem.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/custom/CTabItem.d	Sat May 17 17:34:28 2008 +0200
@@ -23,6 +23,7 @@
 import dwt.graphics.Point;
 import dwt.graphics.RGB;
 import dwt.graphics.Rectangle;
+import dwt.graphics.TextLayout;
 import dwt.widgets.Control;
 import dwt.widgets.Display;
 import dwt.widgets.Item;
@@ -134,13 +135,10 @@
  */
 public this (CTabFolder parent, int style, int index) {
     closeRect = new Rectangle(0, 0, 0, 0);
-    super (parent, checkStyle(style));
+    super (parent, style);
     showClose = (style & DWT.CLOSE) !is 0;
     parent.createItem (this, index);
 }
-static int checkStyle(int style) {
-    return DWT.NONE;
-}
 
 /*
  * Return whether to use ellipses or just truncate labels
@@ -159,16 +157,19 @@
     if (gc.textExtent(text, FLAGS).x <= width) return text;
     int ellipseWidth = gc.textExtent(ellipses, FLAGS).x;
     int length = text.length;
-    int end = length - 1;
+    TextLayout layout = new TextLayout(getDisplay());
+    layout.setText(text);
+    int end = layout.getPreviousOffset(length, DWT.MOVEMENT_CLUSTER);
     while (end > 0) {
         text = text[ 0 .. end ];
         int l = gc.textExtent(text, FLAGS).x;
         if (l + ellipseWidth <= width) {
-            return text ~ ellipses;
+            break;
         }
-        end--;
+        end = layout.getPreviousOffset(end, DWT.MOVEMENT_CLUSTER);
     }
-    return text[ 0 .. 1 ];
+    layout.dispose();
+    return end is 0 ? text.substring(0, 1) : text ~ ellipses;
 }
 
 public override void dispose() {
@@ -767,6 +768,24 @@
     return parent;
 }
 /**
+ * Returns <code>true</code> to indicate that the receiver's close button should be shown.
+ * Otherwise return <code>false</code>. The initial value is defined by the style (DWT.CLOSE)
+ * that was used to create the receiver.
+ * 
+ * @return <code>true</code> if the close button should be shown
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ * 
+ * @since 3.4
+ */
+public bool getShowClose() {
+    checkWidget();
+    return showClose;
+}
+/**
  * Returns the receiver's tool tip text, or null if it has
  * not been set.
  *
@@ -997,6 +1016,27 @@
         parent.redrawTabs();
     }
 }
+/**
+ * Sets to <code>true</code> to indicate that the receiver's close button should be shown.
+ * If the parent (CTabFolder) was created with DWT.CLOSE style, changing this value has
+ * no effect.
+ * 
+ * @param close the new state of the close button
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ * 
+ * @since 3.4
+ */
+public void setShowClose(bool close) {
+    checkWidget();
+    if (showClose is close) return;
+    showClose = close;
+    parent.updateItems();
+    parent.redrawTabs();
+}
 public override void setText (String string) {
     checkWidget();
     if (string is null) DWT.error (DWT.ERROR_NULL_ARGUMENT);
@@ -1024,4 +1064,5 @@
     checkWidget();
     toolTipText = string;
 }
+
 }
--- a/dwt/custom/LineBackgroundEvent.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/custom/LineBackgroundEvent.d	Sat May 17 17:34:28 2008 +0200
@@ -44,6 +44,7 @@
     super(cast(Object)e);
     lineOffset = e.detail;
     lineText = e.text;
+    lineBackground = e.lineBackground;
 }
 }
 
--- a/dwt/custom/LineStyleEvent.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/custom/LineStyleEvent.d	Sat May 17 17:34:28 2008 +0200
@@ -88,6 +88,8 @@
 
 public this(StyledTextEvent e) {
     super(cast(Object)e);
+    styles = e.styles;
+    ranges = e.ranges;
     lineOffset = e.detail;
     lineText = e.text;
     alignment = e.alignment;
--- a/dwt/custom/SashForm.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/custom/SashForm.d	Sat May 17 17:34:28 2008 +0200
@@ -112,6 +112,23 @@
     //checkWidget();
     return (sashStyle & DWT.VERTICAL) !is 0 ? DWT.HORIZONTAL : DWT.VERTICAL;
 }
+/**
+ * Returns the width of the sashes when the controls in the SashForm are 
+ * laid out.
+ * 
+ * @return the width of the sashes
+ * 
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ * 
+ * @since 3.4
+ */
+public int getSashWidth() {
+    checkWidget();
+    return SASH_WIDTH;
+}
 public override int getStyle() {
     int style = super.getStyle();
     style |= getOrientation() is DWT.VERTICAL ? DWT.VERTICAL : DWT.HORIZONTAL;
@@ -361,6 +378,25 @@
 }
 
 /**
+ * Specify the width of the sashes when the controls in the SashForm are 
+ * laid out.
+ * 
+ * @param width the width of the sashes
+ * 
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ * 
+ * @since 3.4
+ */
+public void setSashWidth(int width) {
+    checkWidget();
+    if (SASH_WIDTH is width) return;
+    SASH_WIDTH = width;
+    layout(false);
+}
+/**
  * Specify the relative weight of each child in the SashForm.  This will determine
  * what percent of the total width (if SashForm has Horizontal orientation) or
  * total height (if SashForm has Vertical orientation) each control will occupy.
--- a/dwt/custom/ScrolledComposite.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/custom/ScrolledComposite.d	Sat May 17 17:34:28 2008 +0200
@@ -15,14 +15,18 @@
 
 import dwt.DWT;
 import dwt.DWTException;
+import dwt.events.DisposeEvent;
+import dwt.events.DisposeListener;
 import dwt.graphics.Point;
 import dwt.graphics.Rectangle;
 import dwt.widgets.Composite;
 import dwt.widgets.Control;
+import dwt.widgets.Display;
 import dwt.widgets.Event;
 import dwt.widgets.Layout;
 import dwt.widgets.Listener;
 import dwt.widgets.ScrollBar;
+import dwt.widgets.Shell;
 import dwt.custom.ScrolledCompositeLayout;
 import dwt.dwthelper.utils;
 
@@ -113,12 +117,14 @@
 
     Control content;
     Listener contentListener;
+    Listener filter;
 
     int minHeight = 0;
     int minWidth = 0;
     bool expandHorizontal = false;
     bool expandVertical = false;
     bool alwaysShowScroll = false;
+    bool showFocusedControl = false;
 
 /**
  * Constructs a new instance of this class given its parent
@@ -176,6 +182,20 @@
             layout(false);
         }
     };
+
+    filter = new class() Listener {
+        public void handleEvent(Event event) {
+            if ( auto control = cast(Control)event.widget ) {
+                if (contains(control)) showControl(control);
+            }
+        }
+    };
+
+    addDisposeListener(new class() DisposeListener {
+        public void widgetDisposed(DisposeEvent e) {
+            getDisplay().removeFilter(DWT.FocusIn, filter);
+        }
+    });
 }
 
 static int checkStyle (int style) {
@@ -183,6 +203,17 @@
     return style & mask;
 }
 
+bool contains(Control control) {
+    if (control is null || control.isDisposed()) return false;
+
+    Composite parent = control.getParent();
+    while (parent !is null && !( null !is cast(Shell)parent )) {
+        if (this is parent) return true;
+        parent = parent.getParent();
+    }
+    return false;
+}
+
 /**
  * Returns the Always Show Scrollbars flag.  True if the scrollbars are
  * always shown even if they are not required.  False if the scrollbars are only
@@ -277,6 +308,22 @@
     return content;
 }
 
+/**
+ * Returns <code>true</code> if the receiver automatically scrolls to a focused child control
+ * to make it visible. Otherwise, returns <code>false</code>.
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @since 3.4
+ */
+public bool getShowFocusedControl() {
+    checkWidget();
+    return showFocusedControl;
+}
+
 void hScroll() {
     if (content is null) return;
     Point location = content.getLocation ();
@@ -586,6 +633,66 @@
     setMinSize(width, minHeight);
 }
 
+/**
+ * Configure the receiver to automatically scroll to a focused child control
+ * to make it visible.
+ *
+ * If show is <code>false</code>, show a focused control is off.
+ * By default, show a focused control is off.
+ *
+ * @param show <code>true</code> to show a focused control.
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ *  @since 3.4
+ */
+public void setShowFocusedControl(bool show) {
+    checkWidget();
+    if (showFocusedControl is show) return;
+    Display display = getDisplay();
+    display.removeFilter(DWT.FocusIn, filter);
+    showFocusedControl = show;
+    if (!showFocusedControl) return;
+    display.addFilter(DWT.FocusIn, filter);
+    Control control = display.getFocusControl();
+    if (contains(control)) showControl(control);
+}
+
+/**
+ * Scrolls the content of the receiver so that the control is visible.
+ *
+ * @param control the control to be shown
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the control is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the control has been disposed</li>
+ * </ul>
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @since 3.4
+ */
+public void showControl(Control control) {
+    checkWidget ();
+    if (control is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
+    if (control.isDisposed ()) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
+    if (!contains(control)) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
+
+    Rectangle itemRect = getDisplay().map(control.getParent(), this, control.getBounds());
+    Rectangle area = getClientArea();
+    Point origin = getOrigin();
+    if (itemRect.x < 0) origin.x = Math.max(0, origin.x + itemRect.x);
+    if (itemRect.y < 0) origin.y = Math.max(0, origin.y + itemRect.y);
+    if (area.width < itemRect.x + itemRect.width) origin.x = Math.max(0, origin.x + itemRect.x + itemRect.width - area.width);
+    if (area.height < itemRect.y + itemRect.height) origin.y = Math.max(0, origin.y + itemRect.y + itemRect.height - area.height);
+    setOrigin(origin);
+}
+
 void vScroll() {
     if (content is null) return;
     Point location = content.getLocation ();
--- a/dwt/custom/StyleRange.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/custom/StyleRange.d	Sat May 17 17:34:28 2008 +0200
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2006 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -46,23 +46,23 @@
      */
     public int fontStyle = DWT.NORMAL;
 
-/++
- + DWT extension for clone implementation
- +/
-protected this( StyleRange other ){
-    super( other );
-    start = other.start;
-    length = other.length;
-    fontStyle = other.fontStyle;
-}
-
 /**
  * Create a new style range with no styles
  *
  * @since 3.2
  */
 public this() {
-    super(null, null, null);
+}
+
+/**
+ * Create a new style range from an existing text style.
+ *
+ *@param style the text style to copy
+ *
+ *@since 3.4
+ */
+public this(TextStyle style) {
+    super(style);
 }
 
 /**
@@ -144,6 +144,7 @@
     if (fontStyle !is DWT.NORMAL) return false;
     if (underline) return false;
     if (strikeout) return false;
+    if (borderStyle !is DWT.NONE) return false;
     return true;
 }
 
--- a/dwt/custom/StyledText.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/custom/StyledText.d	Sat May 17 17:34:28 2008 +0200
@@ -56,6 +56,7 @@
 import dwt.widgets.Control;
 import dwt.widgets.Display;
 import dwt.widgets.Event;
+import dwt.widgets.IME;
 import dwt.widgets.Label;
 import dwt.widgets.Listener;
 import dwt.widgets.ScrollBar;
@@ -196,8 +197,8 @@
     Point doubleClickSelection;         // selection after last mouse double click
     bool editable = true;
     bool wordWrap = false;
-    bool doubleClickEnabled = true;  // see getDoubleClickEnabled
-    bool overwrite = false;          // insert/overwrite edit mode
+    bool doubleClickEnabled = true; // see getDoubleClickEnabled
+    bool overwrite = false;         // insert/overwrite edit mode
     int textLimit = -1;                 // limits the number of characters the user can type in the widget. Unlimited by default.
     int[int] keyActionMap;
     Color background = null;            // workaround for bug 4791
@@ -213,14 +214,16 @@
     int lastTextChangeReplaceCharCount;
     int lastLineBottom;                 // the bottom pixel of the last line been replaced
     bool isMirrored_;
-    bool bidiColoring = false;       // apply the BIDI algorithm on text segments of the same color
+    bool bidiColoring = false;      // apply the BIDI algorithm on text segments of the same color
     Image leftCaretBitmap = null;
     Image rightCaretBitmap = null;
     int caretDirection = DWT.NULL;
+    int caretWidth = 0;
     Caret defaultCaret = null;
     bool updateCaretDirection = true;
     bool fixedLineHeight;
     bool dragDetect_ = true;
+    IME ime;
 
     int alignment;
     bool justify;
@@ -260,9 +263,9 @@
         int endPage;                                    // last page to print
         int startLine;                                  // first (wrapped) line to print
         int endLine;                                    // last (wrapped) line to print
-        bool singleLine;                             // widget single line mode
+        bool singleLine;                                // widget single line mode
         Point selection = null;                 // selected text
-        bool mirrored;                       // indicates the printing gc should be mirrored
+        bool mirrored;                      // indicates the printing gc should be mirrored
         int lineSpacing;
         int printMargin;
 
@@ -526,11 +529,24 @@
             printLayout.setFont(printerFont);
         }
         if (printOptions.printLineNumbers) {
+            int numberingWidth = 0;
             int count = endLine - startLine + 1;
-            StringBuffer buffer = new StringBuffer("0");
-            while ((count /= 10) > 0) buffer.append("0");
-            printLayout.setText(buffer.toString());
-            int numberingWidth = printLayout.getBounds().width + printMargin;
+            String[] lineLabels = printOptions.lineLabels;
+            if (lineLabels !is null) {
+                for (int i = startLine; i < Math.min(count, lineLabels.length); i++) {
+                    if (lineLabels[i] !is null) {
+                        printLayout.setText(lineLabels[i]);
+                        int lineWidth = printLayout.getBounds().width;
+                        numberingWidth = Math.max(numberingWidth, lineWidth);
+                    }
+                }
+            } else {
+                StringBuffer buffer = new StringBuffer("0");
+                while ((count /= 10) > 0) buffer.append("0");
+                printLayout.setText(buffer.toString());
+                numberingWidth = printLayout.getBounds().width;
+            }
+            numberingWidth += printMargin;
             if (numberingWidth > width) numberingWidth = width;
             paintX += numberingWidth;
             width -= numberingWidth;
@@ -568,8 +584,9 @@
                 } else {
                     //draw paragraph top in the current page and paragraph bottom in the next
                     int height = paragraphBottom - paintY;
-                    gc.setClipping(paintX, paintY, width, height);
+                    gc.setClipping(clientArea.x, paintY, clientArea.width, height);
                     printLine(paintX, paintY, gc, foreground, lineBackground, layout, printLayout, i);
+                    gc.setClipping(cast(Rectangle)null);
                     printDecoration(page, false, printLayout);
                     printer.endPage();
                     page++;
@@ -578,16 +595,16 @@
                         printDecoration(page, true, printLayout);
                         paintY = clientArea.y - height;
                         int layoutHeight = layout.getBounds().height;
-                        gc.setClipping(paintX, clientArea.y, width, layoutHeight - height);
+                        gc.setClipping(clientArea.x, clientArea.y, clientArea.width, layoutHeight - height);
                         printLine(paintX, paintY, gc, foreground, lineBackground, layout, printLayout, i);
+                        gc.setClipping(cast(Rectangle)null);
                         paintY += layoutHeight;
                     }
-                    gc.setClipping(cast(Rectangle)null);
                 }
             }
             printerRenderer.disposeTextLayout(layout);
         }
-        if (paintY > clientArea.y) {
+        if (page <= endPage && paintY > clientArea.y) {
             // close partial page
             printDecoration(page, false, printLayout);
             printer.endPage();
@@ -674,9 +691,18 @@
         }
         if (printOptions.printLineNumbers) {
             FontMetrics metrics = layout.getLineMetrics(0);
-            printLayout.setAscent(metrics.getAscent() + metrics.getDescent());
+            printLayout.setAscent(metrics.getAscent() + metrics.getLeading());
             printLayout.setDescent(metrics.getDescent());
-            printLayout.setText( to!(String)(index) );
+            String[] lineLabels = printOptions.lineLabels;
+            if (lineLabels !is null) {
+                if (0 <= index && index < lineLabels.length && lineLabels[index] !is null) {
+                    printLayout.setText(lineLabels[index]);
+                } else {
+                    printLayout.setText("");
+                }
+            } else {
+                printLayout.setText( to!(String)(index) );
+            }
             int paintX = x - printMargin - printLayout.getBounds().width;
             printLayout.draw(gc, paintX, y);
             printLayout.setAscent(-1);
@@ -1312,7 +1338,8 @@
     renderer = new StyledTextRenderer(getDisplay(), this);
     renderer.setContent(content);
     renderer.setFont(getFont(), tabLength);
-    defaultCaret = new Caret(this, DWT.NULL);
+    ime = new IME(this, DWT.NONE);
+    defaultCaret = new Caret(this, DWT.NONE);
     if ((style & DWT.WRAP) !is 0) {
         setWordWrap(true);
     }
@@ -1327,7 +1354,7 @@
                 setCaretLocation(newCaretPos, direction);
             }
         };
-        BidiUtil.addLanguageListener(handle, runnable);
+        BidiUtil.addLanguageListener(this, runnable);
     }
     setCaret(defaultCaret);
     calculateScrollBars();
@@ -1751,10 +1778,12 @@
         int maxHeight = display.getClientArea().height;
         for (int lineIndex = 0; lineIndex < lineCount; lineIndex++) {
             TextLayout layout = renderer.getTextLayout(lineIndex);
+            int wrapWidth = layout.getWidth();
             if (wordWrap) layout.setWidth(wHint is 0 ? 1 : wHint);
             Rectangle rect = layout.getBounds();
             height += rect.height;
             width = Math.max(width, rect.width);
+            layout.setWidth(wrapWidth);
             renderer.disposeTextLayout(layout);
             if (isFixedLineHeight() && height > maxHeight) break;
         }
@@ -1943,8 +1972,8 @@
         if (event.button !is 1) return false;
     }
     if (selection.x is selection.y) return false;
-    int offset = getOffsetAtPoint(event.x, event.y);
-    if (offset > selection.x && offset < selection.y) {
+    int offset = getOffsetAtPoint(event.x, event.y, null, true);
+    if (selection.x <= offset && offset < selection.y) {
         return dragDetect(event);
     }
     return false;
@@ -2236,10 +2265,6 @@
  * @param key the character typed by the user
  */
 void doContent(char key) {
-    if (textLimit > 0 &&
-        content.getCharCount() - (selection.y - selection.x) >= textLimit) {
-        return;
-    }
     Event event = new Event();
     event.start = selection.x;
     event.end = selection.y;
@@ -2266,6 +2291,9 @@
         event.text = [key];
     }
     if (event.text !is null) {
+        if (textLimit > 0 && content.getCharCount() - (event.end - event.start) >= textLimit) {
+            return;
+        }
         sendKeyEvent(event);
     }
 }
@@ -2530,8 +2558,7 @@
     int oldCaretAlignment = caretAlignment;
     int newCaretOffset = getOffsetAtPoint(x, y);
 
-    if (clickCount > 1) {
-        // double click word select the previous/next word. fixes bug 15610
+    if (doubleClickEnabled && clickCount > 1) {
         newCaretOffset = doMouseWordSelect(x, newCaretOffset, line);
     }
 
@@ -3246,21 +3273,27 @@
 }
 Rectangle getBoundsAtOffset(int offset) {
     int lineIndex = content.getLineAtOffset(offset);
+    int lineOffset = content.getOffsetAtLine(lineIndex);
     String line = content.getLine(lineIndex);
     Rectangle bounds;
     if (line.length !is 0) {
-        int offsetInLine = offset - content.getOffsetAtLine(lineIndex);
+        int offsetInLine = offset - lineOffset;
         TextLayout layout = renderer.getTextLayout(lineIndex);
         bounds = layout.getBounds(offsetInLine, offsetInLine);
         renderer.disposeTextLayout(layout);
     } else {
         bounds = new Rectangle (0, 0, 0, renderer.getLineHeight());
     }
+    if (offset is caretOffset) {
+        int lineEnd = lineOffset + line.length;
+        if (offset is lineEnd && caretAlignment is PREVIOUS_OFFSET_TRAILING) {
+            bounds.width += getCaretWidth();
+        }
+    }
     bounds.x += leftMargin - horizontalScrollOffset;
     bounds.y += getLinePixel(lineIndex);
     return bounds;
 }
-
 /**
  * Returns the caret position relative to the start of the text.
  *
@@ -3307,11 +3340,11 @@
     return offset;
 }
 /**
- * Returns the content implementation that is used for text storage
- * or null if no user defined content implementation has been set.
- *
- * @return content implementation that is used for text storage or null
- * if no user defined content implementation has been set.
+ * Returns the content implementation that is used for text storage.
+ *
+ * @return content the user defined content implementation that is used for
+ * text storage or the default content implementation if no user defined
+ * content implementation has been set.
  * @exception DWTException <ul>
  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
@@ -3468,6 +3501,32 @@
     return content.getCharCount();
 }
 /**
+ * Returns the line at the given line index without delimiters.
+ * Index 0 is the first line of the content. When there are not
+ * any lines, getLine(0) is a valid call that answers an empty string.
+ * <p>
+ *
+ * @param lineIndex index of the line to return.
+ * @return the line text without delimiters
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ * @exception IllegalArgumentException <ul>
+ *   <li>ERROR_INVALID_RANGE when the line index is outside the valid range (< 0 or >= getLineCount())</li>
+ * </ul>
+ * @since 3.4
+ */
+public String getLine(int lineIndex) {
+    checkWidget();
+    if (lineIndex < 0 ||
+        (lineIndex > 0 && lineIndex >= content.getLineCount())) {
+        DWT.error(DWT.ERROR_INVALID_RANGE);
+    }
+    return content.getLine(lineIndex);
+}
+/**
  * Returns the alignment of the line at the given index.
  *
  * @param index the index of the line
@@ -3859,7 +3918,7 @@
  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  * </ul>
  * @exception IllegalArgumentException <ul>
- *   <li>ERROR_INVALID_RANGE when the offset is outside the valid range (< 0 or > getCharCount())</li>
+ *   <li>ERROR_INVALID_RANGE when the line index is outside the valid range (< 0 or >= getLineCount())</li>
  * </ul>
  * @since 2.0
  */
@@ -3899,32 +3958,12 @@
     if (point is null) {
         DWT.error(DWT.ERROR_NULL_ARGUMENT);
     }
-    // is y above first line or is x before first column?
-    if (point.y + getVerticalScrollOffset() < 0 || point.x + horizontalScrollOffset < 0) {
-        DWT.error(DWT.ERROR_INVALID_ARGUMENT);
-    }
-    int bottomIndex = getLineIndex(clientAreaHeight);
-    int height = getLinePixel(bottomIndex) + renderer.getLineHeight(bottomIndex);
-    if (point.y > height) {
+    int[] trailing = new int[1];
+    int offset = getOffsetAtPoint(point.x, point.y, trailing, true);
+    if (offset is -1) {
         DWT.error(DWT.ERROR_INVALID_ARGUMENT);
     }
-    int lineIndex = getLineIndex(point.y);
-    int lineOffset = content.getOffsetAtLine(lineIndex);
-    TextLayout layout = renderer.getTextLayout(lineIndex);
-    int[] trailing = new int[1];
-    int x = point.x + horizontalScrollOffset - leftMargin ;
-    int y = point.y - getLinePixel(lineIndex);
-    int offsetInLine = layout.getOffset(x, y, trailing);
-    String line = content.getLine(lineIndex);
-    if (offsetInLine !is line.length - 1) {
-        offsetInLine = Math.min(line.length, offsetInLine + trailing[0]);
-    }
-    Rectangle rect = layout.getLineBounds(layout.getLineIndex(offsetInLine));
-    renderer.disposeTextLayout(layout);
-    if (x > rect.x + rect.width) {
-        DWT.error(DWT.ERROR_INVALID_ARGUMENT);
-    }
-    return lineOffset + offsetInLine;
+    return offset + trailing[0];
 }
 int getOffsetAtPoint(int x, int y) {
     int lineIndex = getLineIndex(y);
@@ -3947,7 +3986,6 @@
     caretAlignment = OFFSET_LEADING;
     if (trailing[0] !is 0) {
         int lineInParagraph = layout.getLineIndex(offsetInLine + trailing[0]);
-        //TODO handle bidi text
         int lineStart = layout.getLineOffsets()[lineInParagraph];
         if (offsetInLine + trailing[0] is lineStart) {
             offsetInLine += trailing[0];
@@ -3974,6 +4012,28 @@
     renderer.disposeTextLayout(layout);
     return offsetInLine + content.getOffsetAtLine(lineIndex);
 }
+int getOffsetAtPoint(int x, int y, int[] trailing, bool inTextOnly) {
+    if (inTextOnly && y + getVerticalScrollOffset() < 0 || x + horizontalScrollOffset < 0) {
+        return -1;
+    }
+    int bottomIndex = getPartialBottomIndex();
+    int height = getLinePixel(bottomIndex + 1);
+    if (inTextOnly && y > height) {
+        return -1;
+    }
+    int lineIndex = getLineIndex(y);
+    int lineOffset = content.getOffsetAtLine(lineIndex);
+    TextLayout layout = renderer.getTextLayout(lineIndex);
+    x += horizontalScrollOffset - leftMargin ;
+    y -= getLinePixel(lineIndex);
+    int offset = layout.getOffset(x, y, trailing);
+    Rectangle rect = layout.getLineBounds(layout.getLineIndex(offset));
+    renderer.disposeTextLayout(layout);
+    if (inTextOnly && !(rect.x  <= x && x <=  rect.x + rect.width)) {
+        return -1;
+    }
+    return offset + lineOffset;
+}
 /**
  * Returns the orientation of the receiver.
  *
@@ -3999,7 +4059,7 @@
     if (isFixedLineHeight()) {
         int lineHeight = renderer.getLineHeight();
         int partialLineCount = Compatibility.ceil(clientAreaHeight, lineHeight);
-        return Math.min(content.getLineCount(), topIndex + partialLineCount) - 1;
+        return Math.max(0, Math.min(content.getLineCount(), topIndex + partialLineCount) - 1);
     }
     return getLineIndex(clientAreaHeight - bottomMargin);
 }
@@ -4596,12 +4656,15 @@
     for (int i = lineStart; i <= lineEnd; i++) {
         int lineOffset = content.getOffsetAtLine(i);
         TextLayout layout = renderer.getTextLayout(i);
-        if (layout.getText().length > 0) {
-            if (i is lineStart && i is lineEnd) {
-                rect = layout.getBounds(start - lineOffset, end - lineOffset);
-            } else if (i is lineStart) {
-                String line = content.getLine(i);
-                rect = layout.getBounds(start - lineOffset, line.length);
+        int length = layout.getText().length;
+        if (length > 0) {
+            if (i is lineStart) {
+                if (i is lineEnd) {
+                    rect = layout.getBounds(start - lineOffset, end - lineOffset);
+                } else {
+                    rect = layout.getBounds(start - lineOffset, length);
+                }
+                y += rect.y;
             } else if (i is lineEnd) {
                 rect = layout.getBounds(0, end - lineOffset);
             } else {
@@ -4726,6 +4789,7 @@
 }
 int getCaretDirection() {
     if (!isBidiCaret()) return DWT.DEFAULT;
+    if (ime.getCompositionOffset() !is -1) return DWT.DEFAULT;
     if (!updateCaretDirection && caretDirection !is DWT.NULL) return caretDirection;
     updateCaretDirection = false;
     int caretLine = getCaretLine();
@@ -4753,7 +4817,7 @@
 }
 int getWrapWidth () {
     if (wordWrap && !isSingleLine()) {
-        int width = clientAreaWidth - leftMargin - rightMargin;
+        int width = clientAreaWidth - leftMargin - rightMargin - getCaretWidth();
         return width > 0 ? width : 1;
     }
     return -1;
@@ -4934,6 +4998,15 @@
     addListener(DWT.Paint, listener);
     addListener(DWT.Resize, listener);
     addListener(DWT.Traverse, listener);
+    ime.addListener(DWT.ImeComposition, new class () Listener {
+        public void handleEvent(Event event) {
+            switch (event.detail) {
+                case DWT.COMPOSITION_SELECTION: handleCompositionSelection(event); break;
+                case DWT.COMPOSITION_CHANGED: handleCompositionChanged(event); break;
+                case DWT.COMPOSITION_OFFSET: handleCompositionOffset(event); break;
+            }
+        }
+    });
     if (verticalBar !is null) {
         verticalBar.addListener(DWT.Selection, new class() Listener {
             public void handleEvent(Event event) {
@@ -5037,6 +5110,39 @@
         super.redraw(leftMargin, y, clientAreaWidth - rightMargin - leftMargin, endRect.y - y, false);
     }
 }
+void handleCompositionOffset (Event event) {
+    int[] trailing = new int [1];
+    event.index = getOffsetAtPoint(event.x, event.y, trailing, true);
+    event.count = trailing[0];
+}
+void handleCompositionSelection (Event event) {
+    event.start = selection.x;
+    event.end = selection.y;
+    event.text = getSelectionText();
+}
+void handleCompositionChanged(Event event) {
+    String text = event.text;
+    int start = event.start;
+    int end = event.end;
+    int length = text.length;
+    if (length is ime.getCommitCount()) {
+        content.replaceTextRange(start, end - start, "");
+        caretOffset = start;
+        caretWidth = 0;
+        caretDirection = DWT.NULL;
+    } else {
+        content.replaceTextRange(start, end - start, text);
+        caretOffset = ime.getCaretOffset();
+        if (ime.getWideCaret()) {
+            int lineIndex = getCaretLine();
+            int lineOffset = content.getOffsetAtLine(lineIndex);
+            TextLayout layout = renderer.getTextLayout(lineIndex);
+            caretWidth = layout.getBounds(start - lineOffset, start + length - 1 - lineOffset).width;
+            renderer.disposeTextLayout(layout);
+        }
+    }
+    showCaret();
+}
 /**
  * Frees resources.
  */
@@ -5067,7 +5173,7 @@
         rightCaretBitmap = null;
     }
     if (isBidiCaret()) {
-        BidiUtil.removeLanguageListener(handle);
+        BidiUtil.removeLanguageListener(this);
     }
     selectionBackground = null;
     selectionForeground = null;
@@ -5249,8 +5355,8 @@
                 start = lineOffset;
                 end = lineEnd;
             }
-            selection.x = selection.y = start;
-            selectionAnchor = -1;
+            caretOffset = start;
+            resetSelection();
             caretOffset = end;
             showCaret();
             doMouseSelection();
@@ -5395,6 +5501,10 @@
  * the content change.
  */
 void handleTextChanged(TextChangedEvent event) {
+    int offset = ime.getCompositionOffset();
+    if (offset !is -1 && lastTextChangeStart < offset) {
+        ime.setCompositionOffset(offset + lastTextChangeNewCharCount - lastTextChangeReplaceCharCount);
+    }
     int firstLine = content.getLineAtOffset(lastTextChangeStart);
     resetCache(firstLine, 0);
     if (!isFixedLineHeight() && topIndex > firstLine) {
@@ -5785,7 +5895,7 @@
  * Temporary until DWT provides this
  */
 bool isBidi() {
-    return IS_GTK || BidiUtil.isBidiPlatform() || isMirrored_;
+    return IS_GTK || IS_CARBON || BidiUtil.isBidiPlatform() || isMirrored_;
 }
 bool isBidiCaret() {
     return BidiUtil.isBidiPlatform();
@@ -6512,9 +6622,7 @@
         }
     }
     horizontalScrollOffset += pixels;
-    int oldColumnX = columnX;
     setCaretLocation();
-    columnX = oldColumnX;
     return true;
 }
 /**
@@ -6567,9 +6675,7 @@
         calculateTopIndex(pixels);
         super.redraw();
     }
-    int oldColumnX = columnX;
     setCaretLocation();
-    columnX = oldColumnX;
     return true;
 }
 void scrollText(int srcY, int destY) {
@@ -6704,6 +6810,10 @@
 /**
  * Sets the alignment of the widget. The argument should be one of <code>DWT.LEFT</code>,
  * <code>DWT.CENTER</code> or <code>DWT.RIGHT</code>. The alignment applies for all lines.
+ * </p><p>
+ * Note that if <code>DWT.MULTI</code> is set, then <code>DWT.WRAP</code> must also be set
+ * in order to stabilize the right edge before setting alignment.
+ * </p>
  *
  * @param alignment the new alignment
  *
@@ -6731,6 +6841,7 @@
 public override void setBackground(Color color) {
     checkWidget();
     background = color;
+    super.setBackground(color);
     super.redraw();
 }
 /**
@@ -6800,7 +6911,7 @@
             location.x -= (caret.getSize().x - 1);
         }
         if (isDefaultCaret) {
-            caret.setBounds(location.x, location.y, 0, caretHeight);
+            caret.setBounds(location.x, location.y, caretWidth, caretHeight);
         } else {
             caret.setLocation(location);
         }
@@ -6854,6 +6965,7 @@
             }
             caretOffset = offset;
         }
+        caretAlignment = PREVIOUS_OFFSET_TRAILING;
         // clear the selection if the caret is moved.
         // don't notify listeners about the selection change.
         clearSelection(false);
@@ -7183,7 +7295,10 @@
 /**
  * Sets the alignment of the specified lines. The argument should be one of <code>DWT.LEFT</code>,
  * <code>DWT.CENTER</code> or <code>DWT.RIGHT</code>.
- * <p>
+ * <p><p>
+ * Note that if <code>DWT.MULTI</code> is set, then <code>DWT.WRAP</code> must also be set
+ * in order to stabilize the right edge before setting alignment.
+ * </p>
  * Should not be called if a LineStyleListener has been set since the listener
  * maintains the line attributes.
  * </p><p>
@@ -7489,7 +7604,7 @@
     if ((orientation & DWT.LEFT_TO_RIGHT) !is 0 && !isMirrored()) {
         return;
     }
-    if (!BidiUtil.setOrientation(handle, orientation)) {
+    if (!BidiUtil.setOrientation(this, orientation)) {
         return;
     }
     isMirrored_ = (orientation & DWT.RIGHT_TO_LEFT) !is 0;
@@ -7705,6 +7820,7 @@
             selectionAnchor = selection.x = start;
             caretOffset = selection.y = end;
         }
+        caretAlignment = PREVIOUS_OFFSET_TRAILING;
         internalRedrawRange(selection.x, selection.y - selection.x);
     }
 }
@@ -8004,12 +8120,8 @@
     checkWidget();
     tabLength = tabs;
     renderer.setFont(null, tabs);
-    if (caretOffset > 0) {
-        caretOffset = 0;
-        showCaret();
-        clearSelection(false);
-    }
     resetCache(0, content.getLineCount());
+    setCaretLocation();
     super.redraw();
 }
 /**
--- a/dwt/custom/StyledTextDropTargetEffect.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/custom/StyledTextDropTargetEffect.d	Sat May 17 17:34:28 2008 +0200
@@ -18,6 +18,8 @@
 import dwt.dnd.DropTargetAdapter;
 import dwt.dnd.DropTargetEffect;
 import dwt.dnd.DropTargetEvent;
+import dwt.graphics.FontMetrics;
+import dwt.graphics.GC;
 import dwt.graphics.Point;
 import dwt.graphics.Rectangle;
 import dwt.widgets.Event;
@@ -31,7 +33,7 @@
 
 /**
  * This adapter class provides a default drag under effect (eg. select and scroll)
- * when a drag occurs over a <code>Table</code>.
+ * when a drag occurs over a <code>StyledText</code>.
  *
  * <p>Classes that wish to provide their own drag under effect for a <code>StyledText</code>
  * can extend this class, override the <code>StyledTextDropTargetEffect.dragOver</code>
@@ -172,37 +174,27 @@
                      pt.y >= scrollY && pt.y <= (scrollY + SCROLL_TOLERANCE))) {
                     if (System.currentTimeMillis() >= scrollBeginTime) {
                         Rectangle area = text.getClientArea();
-                        Rectangle bounds = text.getTextBounds(0, 0);
-                        int charWidth = bounds.width;
+                        GC gc = new GC(text);
+                        FontMetrics fm = gc.getFontMetrics();
+                        gc.dispose();
+                        int charWidth = fm.getAverageCharWidth();
                         int scrollAmount = 10*charWidth;
                         if (pt.x < area.x + 3*charWidth) {
                             int leftPixel = text.getHorizontalPixel();
                             text.setHorizontalPixel(leftPixel - scrollAmount);
-                            if (text.getHorizontalPixel() !is leftPixel) {
-                                text.redraw();
-                            }
                         }
                         if (pt.x > area.width - 3*charWidth) {
                             int leftPixel = text.getHorizontalPixel();
                             text.setHorizontalPixel(leftPixel + scrollAmount);
-                            if (text.getHorizontalPixel() !is leftPixel) {
-                                text.redraw();
-                            }
                         }
-                        int lineHeight = bounds.height;
+                        int lineHeight = text.getLineHeight();
                         if (pt.y < area.y + lineHeight) {
                             int topPixel = text.getTopPixel();
                             text.setTopPixel(topPixel - lineHeight);
-                            if (text.getTopPixel() !is topPixel) {
-                                text.redraw();
-                            }
                         }
                         if (pt.y > area.height - lineHeight) {
                             int topPixel = text.getTopPixel();
                             text.setTopPixel(topPixel + lineHeight);
-                            if (text.getTopPixel() !is topPixel) {
-                                text.redraw();
-                            }
                         }
                         scrollBeginTime = 0;
                         scrollX = scrollY = -1;
@@ -216,53 +208,10 @@
         }
 
         if ((effect & DND.FEEDBACK_SELECT) !is 0) {
-            StyledTextContent content = text.getContent();
-            int newOffset = -1;
-            try {
-                newOffset = text.getOffsetAtLocation(pt);
-            } catch ( tango.core.Exception.IllegalArgumentException ex1) {
-                int maxOffset = content.getCharCount();
-                Point maxLocation = text.getLocationAtOffset(maxOffset);
-                if (pt.y >= maxLocation.y) {
-                    try {
-                        newOffset = text.getOffsetAtLocation(new Point(pt.x, maxLocation.y));
-                    } catch (tango.core.Exception.IllegalArgumentException ex2) {
-                        newOffset = maxOffset;
-                    }
-                } else {
-                    try {
-                        int startOffset = text.getOffsetAtLocation(new Point(0, pt.y));
-                        int endOffset = maxOffset;
-                        int line = content.getLineAtOffset(startOffset);
-                        int lineCount = content.getLineCount();
-                        if (line + 1 < lineCount) {
-                            endOffset = content.getOffsetAtLine(line + 1)  - 1;
-                        }
-                        int lineHeight = text.getLineHeight(startOffset);
-                        for (int i = endOffset; i >= startOffset; i--) {
-                            Point p = text.getLocationAtOffset(i);
-                            if (p.x < pt.x && p.y < pt.y && p.y + lineHeight > pt.y) {
-                                newOffset = i;
-                                break;
-                            }
-                        }
-                    } catch (tango.core.Exception.IllegalArgumentException ex2) {
-                        newOffset = -1;
-                    }
-                }
-            }
-            if (newOffset !is -1 && newOffset !is currentOffset) {
-                // check if offset is line delimiter
-                // see StyledText.isLineDelimiter()
-                int line = content.getLineAtOffset(newOffset);
-                int lineOffset = content.getOffsetAtLine(line);
-                int offsetInLine = newOffset - lineOffset;
-                // offsetInLine will be greater than line length if the line
-                // delimiter is longer than one character and the offset is set
-                // in between parts of the line delimiter.
-                if (offsetInLine > content.getLine(line).length) {
-                    newOffset = Math.max(0, newOffset - 1);
-                }
+            int[] trailing = new int [1];
+            int newOffset = text.getOffsetAtPoint(pt.x, pt.y, trailing, false);
+            newOffset += trailing [0];
+            if (newOffset !is currentOffset) {
                 refreshCaret(text, currentOffset, newOffset);
                 currentOffset = newOffset;
             }
--- a/dwt/custom/StyledTextPrintOptions.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/custom/StyledTextPrintOptions.d	Sat May 17 17:34:28 2008 +0200
@@ -95,5 +95,11 @@
      */
     public bool printLineNumbers = false;
 
+    /**
+     * Labels used for printing line numbers.
+     * 
+     * @since 3.4
+     */
+    public String[] lineLabels = null;
 
 }
--- a/dwt/custom/StyledTextRenderer.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/custom/StyledTextRenderer.d	Sat May 17 17:34:28 2008 +0200
@@ -27,6 +27,7 @@
 import dwt.graphics.TextLayout;
 import dwt.graphics.TextStyle;
 import dwt.widgets.Display;
+import dwt.widgets.IME;
 import dwt.widgets.ScrollBar;
 import dwt.custom.StyledText;
 import dwt.custom.Bullet;
@@ -391,16 +392,18 @@
     int selectionStart = selection.x - lineOffset;
     int selectionEnd = selection.y - lineOffset;
     Rectangle client = styledText.getClientArea();
-    Color lineBackground = getLineBackground(lineIndex, widgetBackground);
+    Color lineBackground = getLineBackground(lineIndex, null);
     StyledTextEvent event = styledText.getLineBackgroundData(lineOffset, line);
     if (event !is null && event.lineBackground !is null) lineBackground = event.lineBackground;
-
     int height = layout.getBounds().height;
-    gc.setBackground(lineBackground);
-    styledText.drawBackground(gc, client.x, paintY, client.width, height);
-
+    if (lineBackground !is null) {
+        gc.setBackground(lineBackground);
+        gc.fillRectangle(client.x, paintY, client.width, height);
+    } else {
+        gc.setBackground(widgetBackground);
+        styledText.drawBackground(gc, client.x, paintY, client.width, height);
+    }
     gc.setForeground(widgetForeground);
-    gc.setBackground(lineBackground);
     if (selectionStart is selectionEnd || (selectionEnd <= 0 && selectionStart > lineLength - 1)) {
         layout.draw(gc, paintX, paintY);
     } else {
@@ -663,8 +666,14 @@
     }
     style = newStyles[newStyles.length - 1];
     if (end < style.start + style.length - 1) {
-        if (!includeRanges || ranges is null) newStyles[newStyles.length - 1] = style = cast(StyleRange)style.clone();
-        style.length = end - style.start + 1;
+        if (end < style.start) {
+            StyleRange[] tmp = new StyleRange[newStyles.length - 1];
+            System.arraycopy(newStyles, 0, tmp, 0, newStyles.length - 1);
+            newStyles = tmp;
+        } else {
+            if (!includeRanges || ranges is null) newStyles[newStyles.length - 1] = style = cast(StyleRange)style.clone();
+            style.length = end - style.start + 1;
+        }
     }
     return newStyles;
 }
@@ -868,6 +877,58 @@
         }
     }
     if (lastOffset < length) layout.setStyle(null, lastOffset, length);
+    if (styledText !is null && styledText.ime !is null) {
+        IME ime = styledText.ime;
+        int compositionOffset = ime.getCompositionOffset();
+        if (compositionOffset !is -1) {
+            int commitCount = ime.getCommitCount();
+            int compositionLength = ime.getText().length;
+            if (compositionLength !is commitCount) {
+                int compositionLine = content.getLineAtOffset(compositionOffset);
+                if (compositionLine is lineIndex) {
+                    int[] imeRanges = ime.getRanges();
+                    TextStyle[] imeStyles = ime.getStyles();
+                    if (imeRanges.length > 0) {
+                        for (int i = 0; i < imeStyles.length; i++) {
+                            int start = imeRanges[i*2] - lineOffset;
+                            int end = imeRanges[i*2+1] - lineOffset;
+                            TextStyle imeStyle = imeStyles[i], userStyle;
+                            for (int j = start; j <= end; j++) {
+                                userStyle = layout.getStyle(j);
+                                if (userStyle is null && j > 0) userStyle = layout.getStyle(j - 1);
+                                if (userStyle is null && j + 1 < length) userStyle = layout.getStyle(j + 1);
+                                if (userStyle is null) {
+                                    layout.setStyle(imeStyle, j, j);
+                                } else {
+                                    TextStyle newStyle = new TextStyle(imeStyle);
+                                    if (newStyle.font is null) newStyle.font = userStyle.font;
+                                    if (newStyle.foreground is null) newStyle.foreground = userStyle.foreground;
+                                    if (newStyle.background is null) newStyle.background = userStyle.background;
+                                    layout.setStyle(newStyle, j, j);
+                                }
+                            }
+                        }
+                    } else {
+                        int start = compositionOffset - lineOffset;
+                        int end = start + compositionLength - 1;
+                        TextStyle userStyle = layout.getStyle(start);
+                        if (userStyle is null) {
+                            if (start > 0) userStyle = layout.getStyle(start - 1);
+                            if (userStyle is null && end + 1 < length) userStyle = layout.getStyle(end + 1);
+                            if (userStyle !is null) {
+                                TextStyle newStyle = new TextStyle();
+                                newStyle.font = userStyle.font;
+                                newStyle.foreground = userStyle.foreground;
+                                newStyle.background = userStyle.background;
+                                layout.setStyle(newStyle, start, end);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
     if (styledText !is null && styledText.isFixedLineHeight()) {
         int index = -1;
         int lineCount = layout.getLineCount();
--- a/dwt/custom/TableCursor.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/custom/TableCursor.d	Sat May 17 17:34:28 2008 +0200
@@ -160,6 +160,9 @@
     TableColumn column = null;
     Listener tableListener, resizeListener, disposeItemListener, disposeColumnListener;
 
+    Color background = null;
+    Color foreground = null;
+
     // By default, invert the list selection colors
     static final int BACKGROUND = DWT.COLOR_LIST_SELECTION_TEXT;
     static final int FOREGROUND = DWT.COLOR_LIST_SELECTION;
@@ -253,6 +256,7 @@
 
     disposeItemListener = new class() Listener {
         public void handleEvent(Event event) {
+            unhookRowColumnListeners();
             row = null;
             column = null;
             _resize();
@@ -260,6 +264,7 @@
     };
     disposeColumnListener = new class() Listener {
         public void handleEvent(Event event) {
+            unhookRowColumnListeners();
             row = null;
             column = null;
             _resize();
@@ -319,16 +324,7 @@
 void dispose(Event event) {
     table.removeListener(DWT.FocusIn, tableListener);
     table.removeListener(DWT.MouseDown, tableListener);
-    if (column !is null) {
-        column.removeListener(DWT.Dispose, disposeColumnListener);
-        column.removeListener(DWT.Move, resizeListener);
-        column.removeListener(DWT.Resize, resizeListener);
-        column = null;
-    }
-    if (row !is null) {
-        row.removeListener(DWT.Dispose, disposeItemListener);
-        row = null;
-    }
+    unhookRowColumnListeners();
     ScrollBar hBar = table.getHorizontalBar();
     if (hBar !is null) {
         hBar.removeListener(DWT.Selection, resizeListener);
@@ -492,10 +488,11 @@
 }
 
 void tableFocusIn(Event event) {
-    if (isDisposed())
-        return;
-    if (isVisible())
+    if (isDisposed()) return;
+    if (isVisible()) {
+        if (row is null && column is null) return;
         setFocus();
+    }
 }
 
 void tableMouseDown(Event event) {
@@ -522,7 +519,14 @@
     }
     TableColumn newColumn = null;
     int columnCount = table.getColumnCount();
-    if (columnCount > 0) {
+    if (columnCount is 0) {
+        if ((table.getStyle() & DWT.FULL_SELECTION) is 0) {
+            Rectangle rect = item.getBounds(0);
+            rect.width += lineWidth;
+            rect.height += lineWidth;
+            if (!rect.contains(pt)) return;
+        }
+    } else {
         for (int i = 0; i < columnCount; i++) {
             Rectangle rect = item.getBounds(i);
             rect.width += lineWidth;
@@ -533,6 +537,7 @@
             }
         }
         if (newColumn is null) {
+            if ((table.getStyle() & DWT.FULL_SELECTION) is 0) return;
             newColumn = table.getColumn(0);
         }
     }
@@ -638,6 +643,30 @@
     return column is null ? 0 : table.indexOf(column);
 }
 /**
+ * Returns the background color that the receiver will use to draw.
+ *
+ * @return the receiver's background color
+ */
+public Color getBackground() {
+    checkWidget();
+    if (background is null) {
+        return getDisplay().getSystemColor(BACKGROUND);
+    }
+    return background;
+}
+/**
+ * Returns the foreground color that the receiver will use to draw.
+ *
+ * @return the receiver's foreground color
+ */
+public Color getForeground() {
+    checkWidget();
+    if (foreground is null) {
+        return getDisplay().getSystemColor(FOREGROUND);
+    }
+    return foreground;
+}
+/**
  * Returns the row over which the TableCursor is positioned.
  *
  * @return the item for the current position
@@ -651,14 +680,49 @@
     checkWidget();
     return row;
 }
+/**
+ * Sets the receiver's background color to the color specified
+ * by the argument, or to the default system color for the control
+ * if the argument is null.
+ * <p>
+ * Note: This operation is a hint and may be overridden by the platform.
+ * For example, on Windows the background of a Button cannot be changed.
+ * </p>
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li> 
+ * </ul>
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
 public override void setBackground (Color color) {
-    if (color is null) color = getDisplay().getSystemColor(BACKGROUND);
-    super.setBackground(color);
+    background = color;
+    super.setBackground(getBackground());
     redraw();
 }
+/**
+ * Sets the receiver's foreground color to the color specified
+ * by the argument, or to the default system color for the control
+ * if the argument is null.
+ * <p>
+ * Note: This operation is a hint and may be overridden by the platform.
+ * </p>
+ * @param color the new color (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li> 
+ * </ul>
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
 public override void setForeground (Color color) {
-    if (color is null) color = getDisplay().getSystemColor(FOREGROUND);
-    super.setForeground(color);
+    foreground = color;
+    super.setForeground(getForeground());
     redraw();
 }
 /**
@@ -707,4 +771,16 @@
         DWT.error(DWT.ERROR_INVALID_ARGUMENT);
     setRowColumn(table.indexOf(row), column, false);
 }
+void unhookRowColumnListeners() {
+    if (column !is null) {
+        column.removeListener(DWT.Dispose, disposeColumnListener);
+        column.removeListener(DWT.Move, resizeListener);
+        column.removeListener(DWT.Resize, resizeListener);
+        column = null;
+    }
+    if (row !is null) {
+        row.removeListener(DWT.Dispose, disposeItemListener);
+        row = null;
+    }
 }
+}
--- a/dwt/custom/TableTreeItem.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/custom/TableTreeItem.d	Sat May 17 17:34:28 2008 +0200
@@ -206,7 +206,7 @@
         */
         if (parent.sizeImage is null) {
             int itemHeight = parent.getItemHeight();
-            parent.sizeImage = new Image(null, itemHeight, itemHeight);
+            parent.sizeImage = new Image(parent.getDisplay(), itemHeight, itemHeight);
             GC gc = new GC (parent.sizeImage);
             gc.setBackground(parent.getBackground());
             gc.fillRectangle(0, 0, itemHeight, itemHeight);
--- a/dwt/dnd/Clipboard.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/dnd/Clipboard.d	Sat May 17 17:34:28 2008 +0200
@@ -590,6 +590,7 @@
         STGMEDIUM* stgmedium = new STGMEDIUM();
         stgmedium.tymed = COM.TYMED_HGLOBAL;
         stgmedium.unionField = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, 4);
+        //TODO - should call GlobalLock
         stgmedium.unionField = cast(void*)COM.DROPEFFECT_COPY;
         stgmedium.pUnkForRelease = null;
         COM.MoveMemory(pmedium, stgmedium, STGMEDIUM.sizeof);
@@ -772,7 +773,7 @@
     dataObject.Release();
     if (rc !is COM.S_OK)return types;
     // Loop over enumerator and save any types that match what we are looking for
-    //auto rgelt = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, FORMATETC.sizeof);
+    //int /*long*/ rgelt = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, FORMATETC.sizeof);
     uint[1] pceltFetched;
     FORMATETC rgelt;
     enumFormatetc.Reset();
--- a/dwt/dnd/DND.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/dnd/DND.d	Sat May 17 17:34:28 2008 +0200
@@ -114,7 +114,7 @@
     /**
      * DropTarget Event: the cursor has left the drop target boundaries OR the drop
      * operation has been cancelled (such as by hitting ECS) OR the drop is about to
-     * happen (user has released the mous ebutotn over this target) (value is 2003).
+     * happen (user has released the mouse button over this target) (value is 2003).
      */
     public static const int DragLeave   = 2003;
 
@@ -200,6 +200,25 @@
      */
     public static const int ERROR_INVALID_DATA = 2003;
 
+    /**
+     * DropTarget Key: The string constant for looking up the drop target 
+     * for a control using <code>getData(String)</code>. When a drop target 
+     * is created for a control, it is stored as a property in the control 
+     * using <code>setData(String, Object)</code>.
+     * 
+     * @since 3.4
+     */
+    public static final String DROP_TARGET_KEY = "DropTarget"; //$NON-NLS-1$
+    
+    /**
+     * DragSource Key: The string constant for looking up the drag source 
+     * for a control using <code>getData(String)</code>. When a drag source 
+     * is created for a control, it is stored as a property in the control 
+     * using <code>setData(String, Object)</code>.
+     * 
+     * @since 3.4
+     */
+    public static final String DRAG_SOURCE_KEY = "DragSource"; //$NON-NLS-1$
 
     static const String INIT_DRAG_MESSAGE = "Cannot initialize Drag"; //$NON-NLS-1$
     static const String INIT_DROP_MESSAGE = "Cannot initialize Drop"; //$NON-NLS-1$
--- a/dwt/dnd/DragSource.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/dnd/DragSource.d	Sat May 17 17:34:28 2008 +0200
@@ -142,7 +142,6 @@
     int dataEffect = DND.DROP_NONE;
 
     static const String DEFAULT_DRAG_SOURCE_EFFECT = "DEFAULT_DRAG_SOURCE_EFFECT"; //$NON-NLS-1$
-    static const String DRAGSOURCEID = "DragSource"; //$NON-NLS-1$
     static const int CFSTR_PERFORMEDDROPEFFECT;
     static final TCHAR[] WindowClass = "#32770\0";
     static this(){
@@ -180,10 +179,10 @@
 public this(Control control, int style) {
     super(control, checkStyle(style));
     this.control = control;
-    if (control.getData(DRAGSOURCEID) !is null) {
+    if (control.getData(DND.DRAG_SOURCE_KEY) !is null) {
         DND.error(DND.ERROR_CANNOT_INIT_DRAG);
     }
-    control.setData(DRAGSOURCEID, this);
+    control.setData(DND.DRAG_SOURCE_KEY, this);
     createCOMInterfaces();
     this.AddRef();
 
@@ -251,6 +250,7 @@
  * </ul>
  *
  * @see DragSourceListener
+ * @see #getDragListeners
  * @see #removeDragListener
  * @see DragSourceEvent
  */
@@ -302,7 +302,7 @@
     Display display = control.getDisplay();
     String key = "dwt.internal.win32.runMessagesInIdle"; //$NON-NLS-1$
     Object oldValue = display.getData(key);
-    display.setData(key, new ValueWrapperBool(true));
+    display.setData(key, new Boolean(true));
     ImageList imagelist = null;
     Image image = event.image;
     hwndDrag = null;
@@ -475,6 +475,41 @@
 }
 
 /**
+ * Returns an array of listeners who will be notified when a drag and drop
+ * operation is in progress, by sending it one of the messages defined in
+ * the <code>DragSourceListener</code> interface.
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @see DragSourceListener
+ * @see #addDragListener
+ * @see #removeDragListener
+ * @see DragSourceEvent
+ *
+ * @since 3.4
+ */
+public DragSourceListener[] getDragListeners() {
+    Listener[] listeners = getListeners(DND.DragStart);
+    int length = listeners.length;
+    DragSourceListener[] dragListeners = new DragSourceListener[length];
+    int count = 0;
+    for (int i = 0; i < length; i++) {
+        Listener listener = listeners[i];
+        if ( auto l = cast(DNDListener)listener ) {
+            dragListeners[count] = cast(DragSourceListener) (l.getEventListener());
+            count++;
+        }
+    }
+    if (count is length) return dragListeners;
+    DragSourceListener[] result = new DragSourceListener[count];
+    SimpleType!(DragSourceListener).arraycopy(dragListeners, 0, result, 0, count);
+    return result;
+}
+
+/**
  * Returns the drag effect that is registered for this DragSource.  This drag
  * effect will be used during a drag and drop operation.
  *
@@ -536,7 +571,7 @@
         control.removeListener(DWT.DragDetect, controlListener);
     }
     controlListener = null;
-    control.setData(DRAGSOURCEID, null);
+    control.setData(DND.DRAG_SOURCE_KEY, null);
     control = null;
     transferAgents = null;
 }
@@ -635,6 +670,7 @@
  *
  * @see DragSourceListener
  * @see #addDragListener
+ * @see #getDragListeners
  */
 public void removeDragListener(DragSourceListener listener) {
     if (listener is null) DND.error(DWT.ERROR_NULL_ARGUMENT);
@@ -650,6 +686,7 @@
     if (formatetc.cfFormat is CFSTR_PERFORMEDDROPEFFECT && formatetc.tymed is COM.TYMED_HGLOBAL) {
         STGMEDIUM* stgmedium = new STGMEDIUM();
         COM.MoveMemory(stgmedium, pmedium,STGMEDIUM.sizeof);
+        //TODO - this should be GlobalLock()
         int[1] ptrEffect;
         OS.MoveMemory(ptrEffect.ptr, stgmedium.unionField,4);
         int[1] effect;
--- a/dwt/dnd/DropTarget.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/dnd/DropTarget.d	Sat May 17 17:34:28 2008 +0200
@@ -15,6 +15,7 @@
 import dwt.DWT;
 import dwt.DWTError;
 import dwt.DWTException;
+import dwt.internal.C;
 import dwt.internal.ole.win32.COM;
 import dwt.internal.ole.win32.extras;
 import dwt.internal.ole.win32.OBJIDL;
@@ -115,7 +116,6 @@
     int refCount;
 
     static final String DEFAULT_DROP_TARGET_EFFECT = "DEFAULT_DROP_TARGET_EFFECT"; //$NON-NLS-1$
-    static final String DROPTARGETID = "DropTarget"; //$NON-NLS-1$
 
 /**
  * Creates a new <code>DropTarget</code> to allow data to be dropped on the specified
@@ -151,10 +151,10 @@
 public this(Control control, int style) {
     super (control, checkStyle(style));
     this.control = control;
-    if (control.getData(DROPTARGETID) !is null) {
+    if (control.getData(DND.DROP_TARGET_KEY) !is null) {
         DND.error(DND.ERROR_CANNOT_INIT_DROP);
     }
-    control.setData(DROPTARGETID, this);
+    control.setData(DND.DROP_TARGET_KEY, this);
     createCOMInterfaces();
     this.AddRef();
 
@@ -222,6 +222,7 @@
  * </ul>
  *
  * @see DropTargetListener
+ * @see #getDropListeners
  * @see #removeDropListener
  * @see DropTargetEvent
  */
@@ -259,6 +260,12 @@
     iDropTarget = null;
 }
 
+int DragEnter_64(IDataObject pDataObject, DWORD grfKeyState, long pt, DWORD* pdwEffect) {
+    POINTL point;
+    OS.MoveMemory( &point, &pt, 8);
+    return DragEnter(pDataObject, grfKeyState, point, pdwEffect);
+}
+
 HRESULT DragEnter(IDataObject pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect) {
     selectedDataType = null;
     selectedOperation = DND.DROP_NONE;
@@ -318,6 +325,12 @@
     return COM.S_OK;
 }
 
+int DragOver_64(int grfKeyState, long pt, DWORD* pdwEffect) {
+    POINTL point;
+    OS.MoveMemory(&point, &pt, 8);
+    return DragOver(grfKeyState, point, pdwEffect);
+}
+
 HRESULT DragOver(int grfKeyState, POINTL pt, DWORD* pdwEffect) {
     if (iDataObject is null) return COM.S_FALSE;
     int oldKeyOperation = keyOperation;
@@ -364,6 +377,12 @@
     return COM.S_OK;
 }
 
+int Drop_64(IDataObject pDataObject, int grfKeyState, long pt, DWORD* pdwEffect) {
+    POINTL point;
+    OS.MoveMemory(&point, &pt, 8);
+    return Drop(pDataObject, grfKeyState, point, pdwEffect);
+}
+
 HRESULT Drop(IDataObject pDataObject, int grfKeyState, POINTL pt, DWORD* pdwEffect) {
     DNDEvent event = new DNDEvent();
     event.widget = this;
@@ -450,6 +469,41 @@
 }
 
 /**
+ * Returns an array of listeners who will be notified when a drag and drop
+ * operation is in progress, by sending it one of the messages defined in
+ * the <code>DropTargetListener</code> interface.
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @see DropTargetListener
+ * @see #addDropListener
+ * @see #removeDropListener
+ * @see DropTargetEvent
+ *
+ * @since 3.4
+ */
+public DropTargetListener[] getDropListeners() {
+    Listener[] listeners = getListeners(DND.DragEnter);
+    int length = listeners.length;
+    DropTargetListener[] dropListeners = new DropTargetListener[length];
+    int count = 0;
+    for (int i = 0; i < length; i++) {
+        Listener listener = listeners[i];
+        if (auto l = cast(DNDListener)listener ) {
+            dropListeners[count] = cast(DropTargetListener) (l.getEventListener());
+            count++;
+        }
+    }
+    if (count is length) return dropListeners;
+    DropTargetListener[] result = new DropTargetListener[count];
+    SimpleType!(DropTargetListener).arraycopy(dropListeners, 0, result, 0, count);
+    return result;
+}
+
+/**
  * Returns the drop effect for this DropTarget.  This drop effect will be
  * used during a drag and drop to display the drag under effect on the
  * target widget.
@@ -493,7 +547,7 @@
     if (controlListener !is null)
         control.removeListener(DWT.Dispose, controlListener);
     controlListener = null;
-    control.setData(DROPTARGETID, null);
+    control.setData(DND.DROP_TARGET_KEY, null);
     transferAgents = null;
     control = null;
 
@@ -588,6 +642,7 @@
  *
  * @see DropTargetListener
  * @see #addDropListener
+ * @see #getDropListeners
  */
 public void removeDropListener(DropTargetListener listener) {
     if (listener is null) DND.error (DWT.ERROR_NULL_ARGUMENT);
--- a/dwt/dnd/DropTargetEffect.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/dnd/DropTargetEffect.d	Sat May 17 17:34:28 2008 +0200
@@ -17,8 +17,8 @@
 import dwt.graphics.Point;
 import dwt.graphics.Rectangle;
 import dwt.widgets.Control;
-import dwt.widgets.Item;
 import dwt.widgets.Table;
+import dwt.widgets.TableItem;
 import dwt.widgets.Tree;
 import dwt.widgets.TreeItem;
 import dwt.widgets.Widget;
@@ -107,38 +107,39 @@
     Widget getItem(Table table, int x, int y) {
         Point coordinates = new Point(x, y);
         coordinates = table.toControl(coordinates);
-        Item item = table.getItem(coordinates);
-        if (item is null) {
-            Rectangle area = table.getClientArea();
-            if (area.contains(coordinates)) {
-                // Scan across the width of the table.
-                for (int x1 = area.x; x1 < area.x + area.width; x1++) {
-                    Point pt = new Point(x1, coordinates.y);
-                    item = table.getItem(pt);
-                    if (item !is null) {
-                        break;
-                    }
-                }
-            }
+        TableItem item = table.getItem(coordinates);
+        if (item !is null) return item;
+        Rectangle area = table.getClientArea();
+        int tableBottom = area.y + area.height;
+        int itemCount = table.getItemCount();
+        for (int i=table.getTopIndex(); i<itemCount; i++) {
+            item = table.getItem(i);
+            Rectangle rect = item.getBounds();
+            rect.x = area.x;
+            rect.width = area.width;
+            if (rect.contains(coordinates)) return item;
+            if (rect.y > tableBottom) break;
         }
-        return item;
+        return null;
     }
 
     Widget getItem(Tree tree, int x, int y) {
-        Point coordinates = new Point(x, y);
-        coordinates = tree.toControl(coordinates);
-        Item item = tree.getItem(coordinates);
+        Point point = new Point(x, y);
+        point = tree.toControl(point);
+        TreeItem item = tree.getItem(point);
         if (item is null) {
             Rectangle area = tree.getClientArea();
-            if (area.contains(coordinates)) {
-                // Scan across the width of the tree.
-                for (int x1 = area.x; x1 < area.x + area.width; x1++) {
-                    Point pt = new Point(x1, coordinates.y);
-                    item = tree.getItem(pt);
-                    if (item !is null) {
-                        break;
-                    }
+            if (area.contains(point)) {
+                int treeBottom = area.y + area.height;
+                item = tree.getTopItem();
+                while (item !is null) {
+                    Rectangle rect = item.getBounds();
+                    int itemBottom = rect.y + rect.height;
+                    if (rect.y <= point.y && point.y < itemBottom) return item;
+                    if (itemBottom > treeBottom) break;
+                    item = nextItem(tree, item);
                 }
+                return null;
             }
         }
         return item;
@@ -146,7 +147,7 @@
 
     TreeItem nextItem(Tree tree, TreeItem item) {
         if (item is null) return null;
-        if (item.getExpanded()) return item.getItem(0);
+        if (item.getExpanded() && item.getItemCount() > 0) return item.getItem(0);
         TreeItem childItem = item;
         TreeItem parentItem = childItem.getParentItem();
         int index = parentItem is null ? tree.indexOf(childItem) : parentItem.indexOf(childItem);
--- a/dwt/dnd/HTMLTransfer.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/dnd/HTMLTransfer.d	Sat May 17 17:34:28 2008 +0200
@@ -85,8 +85,8 @@
         DND.error(DND.ERROR_INVALID_DATA);
     }
     String string = ( cast(ArrayWrapperString)object ).array;
-    int codePage = OS.GetACP();
-    int cchMultiByte = OS.WideCharToMultiByte(codePage, 0, StrToTCHARz(string), -1, null, 0, null, null);
+    /* NOTE: CF_HTML uses UTF-8 encoding. */
+    int cchMultiByte = OS.WideCharToMultiByte(OS.CP_UTF8, 0, StrToTCHARz(string), -1, null, 0, null, null);
     if (cchMultiByte is 0) {
         transferData.stgmedium = new STGMEDIUM();
         transferData.result = COM.DV_E_STGMEDIUM;
@@ -130,10 +130,10 @@
     buffer.append(string);
     buffer.append(SUFFIX);
 
-    auto wstrz = StrToTCHARz(codePage,buffer.toString);
-    cchMultiByte = OS.WideCharToMultiByte(codePage, 0, wstrz, -1, null, 0, null, null);
+    auto wstrz = StrToTCHARz(OS.CP_UTF8,buffer.toString);
+    cchMultiByte = OS.WideCharToMultiByte(OS.CP_UTF8, 0, wstrz, -1, null, 0, null, null);
     auto lpMultiByteStr = cast(char*) OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, cchMultiByte);
-    OS.WideCharToMultiByte(codePage, 0, wstrz, -1, lpMultiByteStr, cchMultiByte, null, null);
+    OS.WideCharToMultiByte(OS.CP_UTF8, 0, wstrz, -1, lpMultiByteStr, cchMultiByte, null, null);
     transferData.stgmedium = new STGMEDIUM();
     transferData.stgmedium.tymed = COM.TYMED_HGLOBAL;
     transferData.stgmedium.unionField = lpMultiByteStr;
@@ -168,11 +168,13 @@
         auto lpMultiByteStr = cast(char*) OS.GlobalLock(hMem);
         if (lpMultiByteStr is null) return null;
         try {
-            int codePage = OS.GetACP();
-            auto cchWideChar  = OS.MultiByteToWideChar (codePage, OS.MB_PRECOMPOSED, lpMultiByteStr, -1, null, 0);
+            /* NOTE: CF_HTML uses UTF-8 encoding.
+             * The MSDN documentation for MultiByteToWideChar states that dwFlags must be set to 0 for UTF-8.
+             * Otherwise, the function fails with ERROR_INVALID_FLAGS. */
+            auto cchWideChar  = OS.MultiByteToWideChar (OS.CP_UTF8, 0, lpMultiByteStr, -1, null, 0);
             if (cchWideChar is 0) return null;
             wchar[] lpWideCharStr = new wchar [cchWideChar - 1];
-            OS.MultiByteToWideChar (codePage, OS.MB_PRECOMPOSED, lpMultiByteStr, -1, lpWideCharStr.ptr, lpWideCharStr.length);
+            OS.MultiByteToWideChar (OS.CP_UTF8, 0, lpMultiByteStr, -1, lpWideCharStr.ptr, lpWideCharStr.length);
             String string = WCHARzToStr(lpWideCharStr.ptr);
             int fragmentStart = 0, fragmentEnd = 0;
             int start = string.indexOf(StartFragment) + StartFragment.length;
@@ -197,12 +199,10 @@
                     break;
                 }
             }
-            if (fragmentEnd <= fragmentStart || fragmentEnd > lpWideCharStr.length) return null;
-            /* TO DO:
-             * FragmentStart and FragmentEnd are offsets in original byte stream, not
-             * the wide char version of the byte stream.
-             */
-            String s = string.substring(fragmentStart, fragmentEnd);
+            if (fragmentEnd <= fragmentStart || fragmentEnd > OS.strlen(lpMultiByteStr)) return null;
+            cchWideChar = OS.MultiByteToWideChar (OS.CP_UTF8, 0, lpMultiByteStr+fragmentStart, fragmentEnd - fragmentStart, lpWideCharStr.ptr, lpWideCharStr.length);
+            if (cchWideChar is 0) return null;
+            String s = TCHARsToStr( lpWideCharStr[ 0 .. cchWideChar ] );
             /*
              * Firefox includes <!--StartFragment --> in the fragment, so remove it.
              */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/dnd/ImageTransfer.d	Sat May 17 17:34:28 2008 +0200
@@ -0,0 +1,224 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+module dwt.dnd.ImageTransfer;
+
+import dwt.DWT;
+import dwt.graphics.Image;
+import dwt.graphics.ImageData;
+import dwt.graphics.RGB;
+import dwt.internal.win32.OS;
+import dwt.internal.ole.win32.COM;
+import dwt.internal.ole.win32.OBJIDL;
+
+import dwt.dnd.ByteArrayTransfer;
+import dwt.dnd.TransferData;
+import dwt.dnd.DND;
+
+import dwt.dwthelper.utils;
+
+/**
+ * The class <code>ImageTransfer</code> provides a platform specific mechanism
+ * for converting a Image represented as a java <code>ImageData</code> to a
+ * platform specific representation of the data and vice versa.
+ * See <code>Transfer</code> for additional information.
+ *
+ * <p>An example of a java <code>ImageData</code> is shown
+ * below:</p>
+ *
+ * <code><pre>
+ *     Image image = new Image("C:\temp\img1.gif");
+ *     ImageData imgData = image.getImageData();
+ * </code></pre>
+ *
+ * @since 3.4
+ */
+public class ImageTransfer : ByteArrayTransfer {
+
+    private static ImageTransfer _instance;
+    private static const String CF_DIB = "CF_DIB"; //$NON-NLS-1$
+    private static const int CF_DIBID = COM.CF_DIB;
+
+static this(){
+     _instance = new ImageTransfer();
+}
+
+private this() {
+}
+
+/**
+ * Returns the singleton instance of the ImageTransfer class.
+ *
+ * @return the singleton instance of the ImageTransfer class
+ */
+public static ImageTransfer getInstance () {
+    return _instance;
+}
+
+/**
+ * This implementation of <code>javaToNative</code> converts an ImageData object represented
+ * by java <code>ImageData</code> to a platform specific representation.
+ * For additional information see <code>Transfer#javaToNative</code>.
+ *
+ * @param object a java <code>ImageData</code> containing the ImageData to be
+ * converted
+ * @param transferData an empty <code>TransferData</code> object; this
+ *  object will be filled in on return with the platform specific format of the data
+ */
+public void javaToNative(Object object, TransferData transferData) {
+    if (!checkImage(object) || !isSupportedType(transferData)) {
+        DND.error(DND.ERROR_INVALID_DATA);
+    }
+    ImageData imgData = cast(ImageData)object;
+    if (imgData is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
+
+    int imageSize = imgData.data.length;
+    int imageHeight = imgData.height;
+    int bytesPerLine = imgData.bytesPerLine;
+
+    BITMAPINFOHEADER bmiHeader;
+    bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
+    bmiHeader.biSizeImage = imageSize;
+    bmiHeader.biWidth = imgData.width;
+    bmiHeader.biHeight = imageHeight;
+    bmiHeader.biPlanes = 1;
+    bmiHeader.biBitCount = cast(short)imgData.depth;
+    bmiHeader.biCompression = OS.DIB_RGB_COLORS;
+
+    int colorSize = 0;
+    if (bmiHeader.biBitCount <= 8) {
+        colorSize += (1 << bmiHeader.biBitCount) * 4;
+    }
+    byte[] bmi = new byte[BITMAPINFOHEADER.sizeof + colorSize];
+    OS.MoveMemory(bmi.ptr, &bmiHeader, BITMAPINFOHEADER.sizeof);
+
+    RGB[] rgbs = imgData.palette.getRGBs();
+    if (rgbs !is null && colorSize > 0) {
+        int offset = BITMAPINFOHEADER.sizeof;
+        for (int j = 0; j < rgbs.length; j++) {
+            bmi[offset] = cast(byte)rgbs[j].blue;
+            bmi[offset + 1] = cast(byte)rgbs[j].green;
+            bmi[offset + 2] = cast(byte)rgbs[j].red;
+            bmi[offset + 3] = 0;
+            offset += 4;
+        }
+    }
+    auto newPtr = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, BITMAPINFOHEADER.sizeof + colorSize + imageSize);
+    OS.MoveMemory(newPtr, bmi.ptr, bmi.length);
+    auto pBitDest = newPtr + BITMAPINFOHEADER.sizeof + colorSize;
+
+    if (imageHeight <= 0) {
+        OS.MoveMemory(pBitDest, imgData.data.ptr, imageSize);
+    } else {
+        int offset = 0;
+        pBitDest += bytesPerLine * (imageHeight - 1);
+        byte[] scanline = new byte[bytesPerLine];
+        for (int i = 0; i < imageHeight; i++) {
+            System.arraycopy(imgData.data, offset, scanline, 0, bytesPerLine);
+            OS.MoveMemory(pBitDest, scanline.ptr, bytesPerLine);
+            offset += bytesPerLine;
+            pBitDest -= bytesPerLine;
+        }
+    }
+    transferData.stgmedium = new STGMEDIUM();
+    transferData.stgmedium.tymed = COM.TYMED_HGLOBAL;
+    transferData.stgmedium.unionField = newPtr;
+    transferData.stgmedium.pUnkForRelease = null;
+    transferData.result = COM.S_OK;
+}
+
+
+/**
+ * This implementation of <code>nativeToJava</code> converts a platform specific
+ * representation of an image to java <code>ImageData</code>.
+ * For additional information see <code>Transfer#nativeToJava</code>.
+ *
+ * @param transferData the platform specific representation of the data to be
+ * been converted
+ * @return a java <code>ImageData</code> of the image if
+ * conversion was successful; otherwise null
+ */
+public Object nativeToJava(TransferData transferData) {
+    if (!isSupportedType(transferData) || transferData.pIDataObject is null) return null;
+    IDataObject dataObject = cast(IDataObject)(transferData.pIDataObject);
+    dataObject.AddRef();
+    FORMATETC* formatetc = new FORMATETC();
+    formatetc.cfFormat = COM.CF_DIB;
+    formatetc.ptd = null;
+    formatetc.dwAspect = COM.DVASPECT_CONTENT;
+    formatetc.lindex = -1;
+    formatetc.tymed = COM.TYMED_HGLOBAL;
+    STGMEDIUM* stgmedium = new STGMEDIUM();
+    stgmedium.tymed = COM.TYMED_HGLOBAL;
+    transferData.result = dataObject.GetData(formatetc, stgmedium);
+
+    if (transferData.result !is COM.S_OK) return null;
+    HANDLE hMem = stgmedium.unionField;
+    dataObject.Release();
+    try {
+        auto ptr = OS.GlobalLock(hMem);
+        if (ptr is null) return null;
+        try {
+            BITMAPINFOHEADER bmiHeader;
+            OS.MoveMemory(&bmiHeader, ptr, BITMAPINFOHEADER.sizeof);
+            void* pBits;
+            auto memDib = OS.CreateDIBSection(null,  cast(BITMAPINFO*)ptr, OS.DIB_RGB_COLORS, &pBits, null, 0);
+            if (memDib is null) DWT.error(DWT.ERROR_NO_HANDLES);
+            void* bits = ptr + bmiHeader.biSize;
+            if (bmiHeader.biBitCount <= 8) {
+                bits += (1 << bmiHeader.biBitCount) * 4;
+            } else if (bmiHeader.biCompression is OS.BI_BITFIELDS) {
+                bits += 12;
+            }
+            if (bmiHeader.biHeight < 0) {
+                OS.MoveMemory(pBits, bits, bmiHeader.biSizeImage);
+            } else {
+                DIBSECTION dib;
+                OS.GetObject(memDib, DIBSECTION.sizeof, &dib);
+                int biHeight = dib.biHeight;
+                int scanline = dib.biSizeImage / biHeight;
+                auto pDestBits = pBits;
+                auto pSourceBits = bits + scanline * (biHeight - 1);
+                for (int i = 0; i < biHeight; i++) {
+                    OS.MoveMemory(pDestBits, pSourceBits, scanline);
+                    pDestBits += scanline;
+                    pSourceBits -= scanline;
+                }
+            }
+            Image image = Image.win32_new(null, DWT.BITMAP, memDib);
+            ImageData data = image.getImageData();
+            OS.DeleteObject(memDib);
+            image.dispose();
+            return data;
+        } finally {
+            OS.GlobalUnlock(hMem);
+        }
+    } finally {
+        OS.GlobalFree(hMem);
+    }
+}
+
+protected int[] getTypeIds(){
+    return [CF_DIBID];
+}
+
+protected String[] getTypeNames(){
+    return [CF_DIB];
+}
+bool checkImage(Object object) {
+    if (object is null || !(null !is cast(ImageData)object ))  return false;
+    return true;
+}
+
+protected bool validate(Object object) {
+    return checkImage(object);
+}
+}
+
--- a/dwt/dnd/OleEnumFORMATETC.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/dnd/OleEnumFORMATETC.d	Sat May 17 17:34:28 2008 +0200
@@ -15,6 +15,7 @@
 import dwt.internal.ole.win32.COM;
 import dwt.internal.ole.win32.OBJIDL;
 import dwt.internal.ole.win32.extras;
+import dwt.internal.win32.OS;
 
 final class OleEnumFORMATETC {
 
--- a/dwt/dnd/TableDragSourceEffect.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/dnd/TableDragSourceEffect.d	Sat May 17 17:34:28 2008 +0200
@@ -14,6 +14,8 @@
 
 import dwt.DWT;
 import dwt.graphics.Image;
+import dwt.graphics.ImageData;
+import dwt.graphics.PaletteData;
 import dwt.graphics.Rectangle;
 import dwt.internal.win32.OS;
 import dwt.widgets.Display;
@@ -87,10 +89,78 @@
     Image getDragSourceImage(DragSourceEvent event) {
         if (dragSourceImage !is null) dragSourceImage.dispose();
         dragSourceImage = null;
+        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 1)) {
+            SHDRAGIMAGE shdi;
+            int DI_GETDRAGIMAGE = OS.RegisterWindowMessage ( "ShellGetDragImage"w.ptr ); //$NON-NLS-1$
+            if (OS.SendMessage (control.handle, DI_GETDRAGIMAGE, 0, &shdi) !is 0) {
+                event.x += shdi.ptOffset.x;
+                event.y += shdi.ptOffset.y;
+                auto hImage = shdi.hbmpDragImage;
+                if (hImage !is null) {
+                    BITMAP bm;
+                    OS.GetObject (hImage, BITMAP.sizeof, &bm);
+                    int srcWidth = bm.bmWidth;
+                    int srcHeight = bm.bmHeight;
+
+                    /* Create resources */
+                    auto hdc = OS.GetDC (null);
+                    auto srcHdc = OS.CreateCompatibleDC (hdc);
+                    auto oldSrcBitmap = OS.SelectObject (srcHdc, hImage);
+                    auto memHdc = OS.CreateCompatibleDC (hdc);
+                    BITMAPINFOHEADER bmiHeader;
+                    bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
+                    bmiHeader.biWidth = srcWidth;
+                    bmiHeader.biHeight = -srcHeight;
+                    bmiHeader.biPlanes = 1;
+                    bmiHeader.biBitCount = 32;
+                    bmiHeader.biCompression = OS.BI_RGB;
+                    void* pBits;
+                    auto memDib = OS.CreateDIBSection (null, cast(BITMAPINFO*)&bmiHeader, OS.DIB_RGB_COLORS, &pBits, null, 0);
+                    if (memDib is null) DWT.error (DWT.ERROR_NO_HANDLES);
+                    auto oldMemBitmap = OS.SelectObject (memHdc, memDib);
+
+                    BITMAP dibBM;
+                    OS.GetObject (memDib, BITMAP.sizeof, &dibBM);
+                    int sizeInBytes = dibBM.bmWidthBytes * dibBM.bmHeight;
+
+                    /* Get the foreground pixels */
+                    OS.BitBlt (memHdc, 0, 0, srcWidth, srcHeight, srcHdc, 0, 0, OS.SRCCOPY);
+                    //byte[] srcData = new byte [sizeInBytes];
+                    //OS.MoveMemory (srcData, dibBM.bmBits, sizeInBytes);
+                    byte[] srcData = (cast(byte*) dibBM.bmBits)[ 0 .. BITMAPINFOHEADER.sizeof ];
+
+                    byte[] alphaData = new byte[srcWidth * srcHeight];
+                    int spinc = dibBM.bmWidthBytes - srcWidth * 4;
+                    int ap = 0, sp = 3;
+                    for (int y = 0; y < srcHeight; ++y) {
+                        for (int x = 0; x < srcWidth; ++x) {
+                            alphaData [ap++] = srcData [sp];
+                            sp += 4;
+                        }
+                        sp += spinc;
+                    }
+                    PaletteData palette = new PaletteData(0xFF00, 0xFF0000, 0xFF000000);
+                    ImageData data = new ImageData(srcWidth, srcHeight, bm.bmBitsPixel, palette, bm.bmWidthBytes, srcData);
+                    data.alphaData = alphaData;
+                    data.transparentPixel = shdi.crColorKey;
+                    dragSourceImage = new Image(control.getDisplay(), data);
+                    OS.SelectObject (memHdc, oldMemBitmap);
+                    OS.DeleteDC (memHdc);
+                    OS.DeleteObject (memDib);
+                    OS.SelectObject (srcHdc, oldSrcBitmap);
+                    OS.DeleteDC (srcHdc);
+                    OS.ReleaseDC (null, hdc);
+                    return dragSourceImage;
+                }
+            }
+            return null;
+        }
         Table table = cast(Table) control;
+        //TEMPORARY CODE
+        if (table.isListening (DWT.EraseItem) || table.isListening (DWT.PaintItem)) return null;
         TableItem[] selection = table.getSelection();
         if (selection.length is 0) return null;
-        int tableImageList = OS.SendMessage (table.handle, OS.LVM_GETIMAGELIST, OS.LVSIL_SMALL, 0);
+        int /*long*/ tableImageList = OS.SendMessage (table.handle, OS.LVM_GETIMAGELIST, OS.LVSIL_SMALL, 0);
         if (tableImageList !is 0) {
             int count = Math.min(selection.length, 10);
             Rectangle bounds = selection[0].getBounds(0);
--- a/dwt/dnd/TreeDragSourceEffect.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/dnd/TreeDragSourceEffect.d	Sat May 17 17:34:28 2008 +0200
@@ -14,6 +14,8 @@
 
 import dwt.DWT;
 import dwt.graphics.Image;
+import dwt.graphics.ImageData;
+import dwt.graphics.PaletteData;
 import dwt.graphics.Rectangle;
 import dwt.internal.win32.OS;
 import dwt.widgets.Display;
@@ -86,10 +88,66 @@
     Image getDragSourceImage(DragSourceEvent event) {
         if (dragSourceImage !is null) dragSourceImage.dispose();
         dragSourceImage = null;
+        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 1)) {
+            SHDRAGIMAGE shdi;
+            int DI_GETDRAGIMAGE = OS.RegisterWindowMessage ("ShellGetDragImage"w.ptr); //$NON-NLS-1$
+            if (OS.SendMessage (control.handle, DI_GETDRAGIMAGE, 0, &shdi) !is 0) {
+                event.x += shdi.ptOffset.x;
+                event.y += shdi.ptOffset.y;
+                auto hImage = shdi.hbmpDragImage;
+                if (hImage !is null) {
+                    BITMAP bm;
+                    OS.GetObject (hImage, BITMAP.sizeof, &bm);
+                    int srcWidth = bm.bmWidth;
+                    int srcHeight = bm.bmHeight;
+
+                    /* Create resources */
+                    auto hdc = OS.GetDC (null);
+                    auto srcHdc = OS.CreateCompatibleDC (hdc);
+                    auto oldSrcBitmap = OS.SelectObject (srcHdc, hImage);
+                    auto memHdc = OS.CreateCompatibleDC (hdc);
+                    BITMAPINFOHEADER bmiHeader;
+                    bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
+                    bmiHeader.biWidth = srcWidth;
+                    bmiHeader.biHeight = -srcHeight;
+                    bmiHeader.biPlanes = 1;
+                    bmiHeader.biBitCount = 32;
+                    bmiHeader.biCompression = OS.BI_RGB;
+                    void* pBits;
+                    auto memDib = OS.CreateDIBSection (null, cast(BITMAPINFO*)&bmiHeader, OS.DIB_RGB_COLORS, &pBits, null, 0);
+                    if (memDib is null) DWT.error (DWT.ERROR_NO_HANDLES);
+                    auto oldMemBitmap = OS.SelectObject (memHdc, memDib);
+
+                    BITMAP dibBM;
+                    OS.GetObject (memDib, BITMAP.sizeof, &dibBM);
+                    int sizeInBytes = dibBM.bmWidthBytes * dibBM.bmHeight;
+
+                    /* Get the foreground pixels */
+                    OS.BitBlt (memHdc, 0, 0, srcWidth, srcHeight, srcHdc, 0, 0, OS.SRCCOPY);
+                    byte[] srcData = (cast(byte*)dibBM.bmBits)[ 0 .. sizeInBytes ];
+
+                    PaletteData palette = new PaletteData(0xFF00, 0xFF0000, 0xFF000000);
+                    ImageData data = new ImageData(srcWidth, srcHeight, bm.bmBitsPixel, palette, bm.bmWidthBytes, srcData);
+                    data.transparentPixel = shdi.crColorKey << 8;
+                    dragSourceImage = new Image (control.getDisplay (), data);
+                    OS.SelectObject (memHdc, oldMemBitmap);
+                    OS.DeleteDC (memHdc);
+                    OS.DeleteObject (memDib);
+                    OS.SelectObject (srcHdc, oldSrcBitmap);
+                    OS.DeleteDC (srcHdc);
+                    OS.ReleaseDC (null, hdc);
+                    return dragSourceImage;
+                }
+            }
+            return null;
+        }
+
         Tree tree = cast(Tree) control;
+        //TEMPORARY CODE
+        if (tree.isListening (DWT.EraseItem) || tree.isListening (DWT.PaintItem)) return null;
         TreeItem[] selection = tree.getSelection();
         if (selection.length is 0) return null;
-        int treeImageList = OS.SendMessage (tree.handle, OS.TVM_GETIMAGELIST, OS.TVSIL_NORMAL, 0);
+        auto treeImageList = OS.SendMessage (tree.handle, OS.TVM_GETIMAGELIST, OS.TVSIL_NORMAL, 0);
         if (treeImageList !is 0) {
             int count = Math.min(selection.length, 10);
             Rectangle bounds = selection[0].getBounds(0);
--- a/dwt/dnd/TreeDropTargetEffect.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/dnd/TreeDropTargetEffect.d	Sat May 17 17:34:28 2008 +0200
@@ -12,8 +12,10 @@
  *******************************************************************************/
 module dwt.dnd.TreeDropTargetEffect;
 
+import dwt.DWT;
 import dwt.graphics.Point;
 import dwt.internal.win32.OS;
+import dwt.widgets.Event;
 import dwt.widgets.Tree;
 import dwt.widgets.TreeItem;
 
@@ -59,10 +61,10 @@
     static final int SCROLL_HYSTERESIS = 200; // milli seconds
     static final int EXPAND_HYSTERESIS = 1000; // milli seconds
 
-    int dropIndex;
+    int /*long*/ dropIndex;
     int scrollIndex;
     long scrollBeginTime;
-    int expandIndex;
+    int /*long*/ expandIndex;
     long expandBeginTime;
     TreeItem insertItem;
     bool insertBefore;
@@ -171,22 +173,21 @@
         lpht.pt.x = coordinates.x;
         lpht.pt.y = coordinates.y;
         OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht);
-        int hItem = cast(int) lpht.hItem;
+        auto hItem = lpht.hItem;
         if ((effect & DND.FEEDBACK_SCROLL) is 0) {
             scrollBeginTime = 0;
             scrollIndex = -1;
         } else {
-            if (hItem !is -1 && scrollIndex is hItem && scrollBeginTime !is 0) {
+            if (hItem !is cast(HTREEITEM)-1 && cast(HTREEITEM)scrollIndex is hItem && scrollBeginTime !is 0) {
                 if (System.currentTimeMillis() >= scrollBeginTime) {
-                    int topItem = OS.SendMessage(handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
-                    int nextItem = OS.SendMessage(handle, OS.TVM_GETNEXTITEM, hItem is topItem ? OS.TVGN_PREVIOUSVISIBLE : OS.TVGN_NEXTVISIBLE, hItem);
+                    auto topItem = cast(HTREEITEM)OS.SendMessage(handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
+                    auto nextItem = cast(HTREEITEM)OS.SendMessage(handle, OS.TVM_GETNEXTITEM, hItem is topItem ? OS.TVGN_PREVIOUSVISIBLE : OS.TVGN_NEXTVISIBLE, hItem);
                     bool scroll = true;
                     if (hItem is topItem) {
-                        scroll = nextItem !is 0;
+                        scroll = nextItem !is null;
                     } else {
                         RECT itemRect;
-                        itemRect.left = nextItem;
-                        if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 1, &itemRect) !is 0) {
+                        if (OS.TreeView_GetItemRect (handle, nextItem, &itemRect, true)) {
                             RECT rect;
                             OS.GetClientRect (handle, &rect);
                             POINT pt;
@@ -207,23 +208,23 @@
                 }
             } else {
                 scrollBeginTime = System.currentTimeMillis() + SCROLL_HYSTERESIS;
-                scrollIndex = hItem;
+                scrollIndex = cast(int)hItem;
             }
         }
         if ((effect & DND.FEEDBACK_EXPAND) is 0) {
             expandBeginTime = 0;
             expandIndex = -1;
         } else {
-            if (hItem !is -1 && expandIndex is hItem && expandBeginTime !is 0) {
+            if (cast(int)hItem !is -1 && expandIndex is cast(int)hItem && expandBeginTime !is 0) {
                 if (System.currentTimeMillis() >= expandBeginTime) {
                     if (OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hItem) !is 0) {
-                        TVITEM tvItem;
-                        tvItem.hItem = cast(HANDLE) hItem;
-                        tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
-                        OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem);
-                        if ((tvItem.state & OS.TVIS_EXPANDED) is 0) {
-                            OS.SendMessage (handle, OS.TVM_EXPAND, OS.TVE_EXPAND, hItem);
+                        TreeItem item = cast(TreeItem)tree.getDisplay().findWidget(tree.handle, cast(int)hItem);
+                        if (item !is null && !item.getExpanded()) {
+                            item.setExpanded(true);
                             tree.redraw();
+                            Event expandEvent = new Event ();
+                            expandEvent.item = item;
+                            tree.notifyListeners(DWT.Expand, expandEvent);
                         }
                     }
                     expandBeginTime = 0;
@@ -231,10 +232,10 @@
                 }
             } else {
                 expandBeginTime = System.currentTimeMillis() + EXPAND_HYSTERESIS;
-                expandIndex = hItem;
+                expandIndex = cast(int)hItem;
             }
         }
-        if (dropIndex !is -1 && (dropIndex !is hItem || (effect & DND.FEEDBACK_SELECT) is 0)) {
+        if (dropIndex !is -1 && (dropIndex !is cast(int)hItem || (effect & DND.FEEDBACK_SELECT) is 0)) {
             TVITEM tvItem;
             tvItem.hItem = cast(HANDLE) dropIndex;
             tvItem.mask = OS.TVIF_STATE;
@@ -243,14 +244,14 @@
             OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
             dropIndex = -1;
         }
-        if (hItem !is -1 && hItem !is dropIndex && (effect & DND.FEEDBACK_SELECT) !is 0) {
+        if (cast(int)hItem !is -1 && cast(int)hItem !is dropIndex && (effect & DND.FEEDBACK_SELECT) !is 0) {
             TVITEM tvItem;
             tvItem.hItem = cast(HANDLE) hItem;
             tvItem.mask = OS.TVIF_STATE;
             tvItem.stateMask = OS.TVIS_DROPHILITED;
             tvItem.state = OS.TVIS_DROPHILITED;
             OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
-            dropIndex = hItem;
+            dropIndex = cast(int)hItem;
         }
         if ((effect & DND.FEEDBACK_INSERT_BEFORE) !is 0 || (effect & DND.FEEDBACK_INSERT_AFTER) !is 0) {
             bool before = (effect & DND.FEEDBACK_INSERT_BEFORE) !is 0;
@@ -263,7 +264,7 @@
             * Since the insert mark can not be queried from the tree,
             * use the Tree API rather than calling the OS directly.
             */
-            TreeItem item = cast(TreeItem)tree.getDisplay().findWidget(tree.handle, hItem);
+            TreeItem item = cast(TreeItem)tree.getDisplay().findWidget(tree.handle, cast(int)hItem);
             if (item !is null) {
                 if (item !is insertItem || before !is insertBefore) {
                     tree.setInsertMark(item, before);
--- a/dwt/dnd/URLTransfer.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/dnd/URLTransfer.d	Sat May 17 17:34:28 2008 +0200
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 20007 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -12,8 +12,6 @@
  *******************************************************************************/
 module dwt.dnd.URLTransfer;
 
-//import java.net.URL;
-
 import dwt.internal.ole.win32.COM;
 import dwt.internal.ole.win32.OBJIDL;
 import dwt.internal.win32.OS;
@@ -28,21 +26,19 @@
 
 /**
  * The class <code>URLTransfer</code> provides a platform specific mechanism
- * for converting text in URL format represented as a java <code>String[]</code>
+ * for converting text in URL format represented as a java <code>String</code> 
  * to a platform specific representation of the data and vice versa.  See
- * <code>Transfer</code> for additional information. The first string in the
- * array is mandatory and must contain the fully specified url.  The second
- * string in the array is optional and if present contains the title for the
- * page.
+ * <code>Transfer</code> for additional information. The string 
+ * must contain a fully specified url.
  *
- * <p>An example of a java <code>String[]</code> containing a URL is shown
+ * <p>An example of a java <code>String</code> containing a URL is shown 
  * below:</p>
  *
  * <code><pre>
- *     String[] urlData = new String[] {"http://www.eclipse.org", "Eclipse.org Main Page"};
+ *     String url = "http://www.eclipse.org";
  * </code></pre>
  */
-/*public*/ class URLTransfer : ByteArrayTransfer {
+public class URLTransfer : ByteArrayTransfer {
 
     static URLTransfer _instance;
     static const String CFSTR_INETURL = "UniformResourceLocator"; //$NON-NLS-1$
@@ -71,11 +67,11 @@
 }
 
 /**
- * This implementation of <code>javaToNative</code> converts a URL and optionally a title
- * represented by a java <code>String[]</code> to a platform specific representation.
+ * This implementation of <code>javaToNative</code> converts a URL
+ * represented by a java <code>String</code> to a platform specific representation.
  * For additional information see <code>Transfer#javaToNative</code>.
  *
- * @param object a java <code>String[]</code> containing a URL and optionally, a title
+ * @param object a java <code>String</code> containing a URL
  * @param transferData an empty <code>TransferData</code> object; this
  *  object will be filled in on return with the platform specific format of the data
  */
@@ -85,7 +81,7 @@
     }
     transferData.result = COM.E_FAIL;
     // URL is stored as a null terminated byte array
-    String url = (cast(ArrayWrapperString2)object).array[0];
+    String url = (cast(ArrayWrapperString)object).array;
     int codePage = OS.GetACP();
     wchar[] chars = StrToWCHARs(codePage, url, true );
     int cchMultiByte = OS.WideCharToMultiByte(codePage, 0, chars.ptr, -1, null, 0, null, null);
@@ -106,12 +102,12 @@
 
 /**
  * This implementation of <code>nativeToJava</code> converts a platform specific
- * representation of a URL and optionally, a title to a java <code>String[]</code>.
+ * representation of a URL to a java <code>String</code>.
  * For additional information see <code>Transfer#nativeToJava</code>.
  *
  * @param transferData the platform specific representation of the data to be
- * been converted
- * @return a java <code>String[]</code> containing a URL and optionally a title if the
+ * converted
+ * @return a java <code>String</code> containing a URL if the 
  * conversion was successful; otherwise null
  */
 public Object nativeToJava(TransferData transferData){
@@ -134,7 +130,7 @@
             if (cchWideChar is 0) return null;
             wchar[] lpWideCharStr = new wchar [cchWideChar - 1];
             OS.MultiByteToWideChar (codePage, OS.MB_PRECOMPOSED, lpMultiByteStr, -1, lpWideCharStr.ptr, lpWideCharStr.length);
-            return new ArrayWrapperString2( [ WCHARzToStr( lpWideCharStr.ptr) ]);
+            return new ArrayWrapperString( WCHARzToStr( lpWideCharStr.ptr) );
         } finally {
             OS.GlobalUnlock(hMem);
         }
@@ -152,19 +148,8 @@
 }
 
 bool checkURL(Object object) {
-    if( auto s = cast(ArrayWrapperString2)object ){
-        if( s.array.length is 0 ) return false;
-        String[] strings = s.array;
-        if (strings[0] is null || strings[0].length is 0) return false;
-        //PORTING_FIXME: how to validata URL?
-        /+try {
-            new URL(strings[0]);
-        } catch (java.net.MalformedURLException e) {
-            return false;
-        }+/
-        return true;
-    }
-    return false;
+    return object !is null && (null !is cast(ArrayWrapperString)object) && (cast(ArrayWrapperString)object).array.length > 0;
+
 }
 
 protected bool validate(Object object) {
--- a/dwt/graphics/Color.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/graphics/Color.d	Sat May 17 17:34:28 2008 +0200
@@ -40,6 +40,8 @@
 
 public final class Color : Resource {
 
+    alias Resource.init_ init_;
+
     /**
      * the handle to the OS color resource
      * (Warning: This field is platform dependent)
@@ -55,7 +57,8 @@
 /**
  * Prevents uninitialized instances from being created outside the package.
  */
-this() {
+this(Device device) {
+    super(device);
 }
 
 /**
@@ -83,10 +86,9 @@
  * @see #dispose
  */
 public this (Device device, int red, int green, int blue) {
-    if (device is null) device = Device.getDevice();
-    if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
-    init_(device, red, green, blue);
-    if (device.tracking) device.new_Object(this);
+    super(device);
+    init_(red, green, blue);
+    init_();
 }
 
 /**
@@ -112,22 +114,13 @@
  * @see #dispose
  */
 public this (Device device, RGB rgb) {
-    if (device is null) device = Device.getDevice();
-    if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
+    super(device);
     if (rgb is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
-    init_(device, rgb.red, rgb.green, rgb.blue);
-    if (device.tracking) device.new_Object(this);
+    init_(rgb.red, rgb.green, rgb.blue);
+    init_();
 }
 
-/**
- * Disposes of the operating system resources associated with
- * the color. Applications must dispose of all colors which
- * they allocate.
- */
-override public void dispose() {
-    if (handle is -1) return;
-    if (device.isDisposed()) return;
-
+void destroy() {
     /*
      * If this is a palette-based device,
      * Decrease the reference count for this color.
@@ -143,8 +136,6 @@
         }
     }
     handle = -1;
-    if (device.tracking) device.dispose_Object(this);
-    device = null;
 }
 
 /**
@@ -249,11 +240,10 @@
  *
  * @see #dispose
  */
-void init_(Device device, int red, int green, int blue) {
+void init_(int red, int green, int blue) {
     if (red > 255 || red < 0 || green > 255 || green < 0 || blue > 255 || blue < 0) {
         DWT.error(DWT.ERROR_INVALID_ARGUMENT);
     }
-    this.device = device;
     handle = (red & 0xFF) | ((green & 0xFF) << 8) | ((blue & 0xFF) << 16);
 
     /* If this is not a palette-based device, return */
@@ -338,10 +328,8 @@
  * @return a new color object containing the specified device and handle
  */
 public static Color win32_new(Device device, int handle) {
-    if (device is null) device = Device.getDevice();
-    Color color = new Color();
+    Color color = new Color(device);
     color.handle = handle;
-    color.device = device;
     return color;
 }
 
--- a/dwt/graphics/Cursor.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/graphics/Cursor.d	Sat May 17 17:34:28 2008 +0200
@@ -54,6 +54,8 @@
 
 public final class Cursor : Resource {
 
+    alias Resource.init_ init_;
+
     /**
      * the handle to the OS cursor resource
      * (Warning: This field is platform dependent)
@@ -149,7 +151,8 @@
 /**
  * Prevents uninitialized instances from being created outside the package.
  */
-this() {
+this(Device device) {
+    super(device);
 }
 
 /**
@@ -194,10 +197,8 @@
  * @see DWT#CURSOR_HAND
  */
 public this(Device device, int style) {
-    if (device is null) device = Device.getDevice();
-    if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
-    this.device = device;
-    int lpCursorName = 0;
+    super(device);
+    int /*long*/ lpCursorName = 0;
     switch (style) {
         case DWT.CURSOR_HAND:       lpCursorName = OS.IDC_HAND; break;
         case DWT.CURSOR_ARROW:      lpCursorName = OS.IDC_ARROW; break;
@@ -240,7 +241,7 @@
         }
     }
     if (handle is null) DWT.error(DWT.ERROR_NO_HANDLES);
-    if (device.tracking) device.new_Object(this);
+    init_();
 }
 
 /**
@@ -275,9 +276,7 @@
  * </ul>
  */
 public this(Device device, ImageData source, ImageData mask, int hotspotX, int hotspotY) {
-    if (device is null) device = Device.getDevice();
-    if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
-    this.device = device;
+    super(device);
     if (source is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
     if (mask is null) {
         if (source.getTransparencyType() !is DWT.TRANSPARENCY_MASK) {
@@ -307,7 +306,7 @@
     static if (OS.IsWinCE) DWT.error (DWT.ERROR_NOT_IMPLEMENTED);
     handle = OS.CreateCursor(hInst, hotspotX, hotspotY, source.width, source.height, sourceData.ptr, maskData.ptr);
     if (handle is null) DWT.error(DWT.ERROR_NO_HANDLES);
-    if (device.tracking) device.new_Object(this);
+    init_();
 }
 
 /**
@@ -338,9 +337,7 @@
  * @since 3.0
  */
 public this(Device device, ImageData source, int hotspotX, int hotspotY) {
-    if (device is null) device = Device.getDevice();
-    if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
-    this.device = device;
+    super(device);
     if (source is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
     /* Check the hotspots */
     if (hotspotX >= source.width || hotspotX < 0 ||
@@ -348,7 +345,7 @@
         DWT.error(DWT.ERROR_INVALID_ARGUMENT);
     }
     ImageData mask = source.getTransparencyMask();
-    int[] result = Image.init_(device, null, source, mask);
+    int[] result = Image.init_(this.device, null, source, mask);
     auto hBitmap = cast(HBITMAP)result[0];
     auto hMask = cast(HBITMAP)result[1];
     /* Create the icon */
@@ -363,18 +360,10 @@
     OS.DeleteObject(hBitmap);
     OS.DeleteObject(hMask);
     isIcon = true;
-    if (device.tracking) device.new_Object(this);
+    init_();
 }
 
-/**
- * Disposes of the operating system resources associated with
- * the cursor. Applications must dispose of all cursors which
- * they allocate.
- */
-override public void dispose () {
-    if (handle is null) return;
-    if (device.isDisposed()) return;
-
+void destroy () {
     /*
     * It is an error in Windows to destroy the current
     * cursor.  Check that the cursor that is about to
@@ -402,8 +391,6 @@
         static if (!OS.IsWinCE) OS.DestroyCursor(handle);
     }
     handle = null;
-    if (device.tracking) device.dispose_Object(this);
-    device = null;
 }
 
 /**
@@ -477,10 +464,8 @@
  * @return a new cursor object containing the specified device and handle
  */
 public static Cursor win32_new(Device device, HCURSOR handle) {
-    if (device is null) device = Device.getDevice();
-    Cursor cursor = new Cursor();
+    Cursor cursor = new Cursor(device);
     cursor.handle = handle;
-    cursor.device = device;
     return cursor;
 }
 
--- a/dwt/graphics/Device.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/graphics/Device.d	Sat May 17 17:34:28 2008 +0200
@@ -17,6 +17,14 @@
 import dwt.internal.gdip.Gdip;
 import dwt.internal.win32.OS;
 
+import dwt.graphics.Cursor;
+import dwt.graphics.GC;
+import dwt.graphics.Image;
+import dwt.graphics.Path;
+import dwt.graphics.Pattern;
+import dwt.graphics.Region;
+import dwt.graphics.TextLayout;
+import dwt.graphics.Transform;
 import dwt.graphics.Drawable;
 import dwt.graphics.DeviceData;
 import dwt.graphics.Rectangle;
@@ -27,8 +35,11 @@
 
 import dwt.dwthelper.Runnable;
 import dwt.dwthelper.System;
+
 import dwt.dwthelper.utils;
 import tango.core.Exception;
+import tango.util.Convert;
+import tango.io.Stdout;
 
 /**
  * This class is the abstract superclass of all device objects,
@@ -49,6 +60,7 @@
     bool tracking;
     Exception [] errors;
     Object [] objects;
+    Object trackingLock;
 
     /**
      * Palette
@@ -64,7 +76,7 @@
     int [] colorRefCount;
 
     /* System Font */
-    HFONT systemFont;
+    Font systemFont;
 
     /* Font Enumeration */
     int nFonts = 256;
@@ -74,6 +86,7 @@
 
     /* Scripts */
     SCRIPT_PROPERTIES*[] scripts;
+    LOGFONT* [] logFontsCache;
 
     /* Advanced Graphics */
     ULONG_PTR gdipToken;
@@ -134,22 +147,20 @@
  * @see DeviceData
  */
 public this(DeviceData data) {
-    synchronized (this.classinfo) {
+    synchronized (Device.classinfo) {
         debug_ = DEBUG;
         tracking = DEBUG;
         if (data !is null) {
             debug_ = data.debug_;
             tracking = data.tracking;
         }
-        create (data);
-        init_ ();
         if (tracking) {
             errors = new Exception [128];
             objects = new Object [128];
+            trackingLock = new Object ();
         }
-
-        /* Initialize the system font slot */
-        systemFont = getSystemFont().handle;
+        create (data);
+        init_ ();
         gdipToken = 0;
     }
 }
@@ -179,8 +190,8 @@
 
 void checkGDIP() {
     if (gdipToken) return;
-    static if (OS.IsWinCE) DWT.error(DWT.ERROR_NOT_IMPLEMENTED);
-    int oldErrorMode = OS.SetErrorMode (OS.SEM_FAILCRITICALERRORS);
+    int oldErrorMode = 0;
+    static if (!OS.IsWinCE) oldErrorMode = OS.SetErrorMode (OS.SEM_FAILCRITICALERRORS);
     try {
         ULONG_PTR token;
         GdiplusStartupInput input;
@@ -191,7 +202,7 @@
     } catch (Exception t) {
         DWT.error (DWT.ERROR_NO_GRAPHICS_LIBRARY, t, " [GDI+ is required]"); //$NON-NLS-1$
     } finally {
-        OS.SetErrorMode (oldErrorMode);
+        if (!OS.IsWinCE) OS.SetErrorMode (oldErrorMode);
     }
 }
 
@@ -272,23 +283,31 @@
  * @see #checkDevice
  */
 public void dispose () {
-    if (isDisposed()) return;
-    checkDevice ();
-    release ();
-    destroy ();
-    disposed = true;
-    if (tracking) {
-        objects = null;
-        errors = null;
+    synchronized (Device.classinfo) {
+        if (isDisposed()) return;
+        checkDevice ();
+        release ();
+        destroy ();
+        disposed = true;
+        if (tracking) {
+            synchronized (trackingLock) {
+                printErrors ();
+                objects = null;
+                errors = null;
+                trackingLock = null;
+            }
+        }
     }
 }
 
 void dispose_Object (Object object) {
-    for (int i=0; i<objects.length; i++) {
-        if (objects [i] is object) {
-            objects [i] = null;
-            errors [i] = null;
-            return;
+    synchronized (trackingLock) {
+        for (int i=0; i<objects.length; i++) {
+            if (objects [i] is object) {
+                objects [i] = null;
+                errors [i] = null;
+                return;
+            }
         }
     }
 }
@@ -369,20 +388,26 @@
     DeviceData data = new DeviceData ();
     data.debug_ = debug_;
     data.tracking = tracking;
-    int count = 0, length = 0;
-    if (tracking) length = objects.length;
-    for (int i=0; i<length; i++) {
-        if (objects [i] !is null) count++;
-    }
-    int index = 0;
-    data.objects = new Object [count];
-    data.errors = new Exception [count];
-    for (int i=0; i<length; i++) {
-        if (objects [i] !is null) {
-            data.objects [index] = objects [i];
-            data.errors [index] = errors [i];
-            index++;
+    if (tracking) {
+        synchronized (trackingLock) {
+            int count = 0, length = objects.length;
+            for (int i=0; i<length; i++) {
+                if (objects [i] !is null) count++;
+            }
+            int index = 0;
+            data.objects = new Object [count];
+            data.errors = new Exception [count];
+            for (int i=0; i<length; i++) {
+                if (objects [i] !is null) {
+                    data.objects [index] = objects [i];
+                    data.errors [index] = errors [i];
+                    index++;
+                }
+            }
         }
+    } else {
+        data.objects = new Object [0];
+        data.errors = new Exception [0];
     }
     return data;
 }
@@ -660,6 +685,9 @@
         static if (!OS.IsWinCE) OS.GdiSetBatchLimit(1);
     }
 
+    /* Initialize the system font slot */
+    systemFont = getSystemFont();
+
     /* Initialize scripts list */
     static if (!OS.IsWinCE) {
         SCRIPT_PROPERTIES** ppSp;
@@ -772,7 +800,9 @@
  * @return <code>true</code> when the device is disposed and <code>false</code> otherwise
  */
 public bool isDisposed () {
-    return disposed;
+    synchronized (Device.classinfo) {
+        return disposed;
+    }
 }
 
 /**
@@ -802,21 +832,71 @@
 }
 
 void new_Object (Object object) {
-    for (int i=0; i<objects.length; i++) {
-        if (objects [i] is null) {
-            objects [i] = object;
-            errors [i] = new Exception ( "" );
-            return;
+    synchronized (trackingLock) {
+        for (int i=0; i<objects.length; i++) {
+            if (objects [i] is null) {
+                objects [i] = object;
+                errors [i] = new Exception ( "" );
+                return;
+            }
+        }
+        Object [] newObjects = new Object [objects.length + 128];
+        System.arraycopy (objects, 0, newObjects, 0, objects.length);
+        newObjects [objects.length] = object;
+        objects = newObjects;
+        Exception [] newErrors = new Exception [errors.length + 128];
+        System.arraycopy (errors, 0, newErrors, 0, errors.length);
+        newErrors [errors.length] = new Exception ("");
+        errors = newErrors;
+    }
+}
+
+void printErrors () {
+    if (!DEBUG) return;
+    if (tracking) {
+        synchronized (trackingLock) {
+            if (objects is null || errors is null) return;
+            int objectCount = 0;
+            int colors = 0, cursors = 0, fonts = 0, gcs = 0, images = 0;
+            int paths = 0, patterns = 0, regions = 0, textLayouts = 0, transforms = 0;
+            for (int i=0; i<objects.length; i++) {
+                Object object = objects [i];
+                if (object !is null) {
+                    objectCount++;
+                    if (null !is cast(Color)object ) colors++;
+                    if (null !is cast(Cursor)object ) cursors++;
+                    if (null !is cast(Font)object ) fonts++;
+                    if (null !is cast(GC)object ) gcs++;
+                    if (null !is cast(Image)object ) images++;
+                    if (null !is cast(Path)object ) paths++;
+                    if (null !is cast(Pattern)object ) patterns++;
+                    if (null !is cast(Region)object ) regions++;
+                    if (null !is cast(TextLayout)object ) textLayouts++;
+                    if (null !is cast(Transform)object ) transforms++;
+                }
+            }
+            if (objectCount !is 0) {
+                String string = "Summary: ";
+                if (colors !is 0) string ~= to!(String)(colors) ~ " Color(s), ";
+                if (cursors !is 0) string ~= to!(String)(cursors) ~ " Cursor(s), ";
+                if (fonts !is 0) string ~= to!(String)(fonts) ~ " Font(s), ";
+                if (gcs !is 0) string ~= to!(String)(gcs) ~ " GC(s), ";
+                if (images !is 0) string ~= to!(String)(images) ~ " Image(s), ";
+                if (paths !is 0) string ~= to!(String)(paths) ~ " Path(s), ";
+                if (patterns !is 0) string ~= to!(String)(patterns) ~ " Pattern(s), ";
+                if (regions !is 0) string ~= to!(String)(regions) ~ " Region(s), ";
+                if (textLayouts !is 0) string ~= to!(String)(textLayouts) ~ " TextLayout(s), ";
+                if (transforms !is 0) string ~= to!(String)(transforms) ~ " Transforms(s), ";
+                if (string.length !is 0) {
+                    string = string.substring (0, string.length - 2);
+                    Stderr.formatln ( "{}", string);
+                }
+                for (int i=0; i<errors.length; i++) {
+                    if (errors [i] !is null) ExceptionPrintStackTrace( errors [i], Stderr);
+                }
+            }
         }
     }
-    Object [] newObjects = new Object [objects.length + 128];
-    System.arraycopy (objects, 0, newObjects, 0, objects.length);
-    newObjects [objects.length] = object;
-    objects = newObjects;
-    Exception [] newErrors = new Exception [errors.length + 128];
-    System.arraycopy (errors, 0, newErrors, 0, errors.length);
-    newErrors [errors.length] = new Exception ("");
-    errors = newErrors;
 }
 
 /**
@@ -848,6 +928,7 @@
     }
     gdipToken = 0; // TODO: assignment of 0 might not be valid for token
     scripts = null;
+    logFontsCache = null;
     if (hPalette !is null) OS.DeleteObject (hPalette);
     hPalette = null;
     colorRefCount = null;
--- a/dwt/graphics/Font.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/graphics/Font.d	Sat May 17 17:34:28 2008 +0200
@@ -42,6 +42,7 @@
 
 public final class Font : Resource {
 
+    alias Resource.init_ init_;
     /**
      * the handle to the OS font resource
      * (Warning: This field is platform dependent)
@@ -57,7 +58,8 @@
 /**
  * Prevents uninitialized instances from being created outside the package.
  */
-this() {
+this(Device device) {
+    super(device);
 }
 
 /**
@@ -79,10 +81,9 @@
  * </ul>
  */
 public this(Device device, FontData fd) {
-    if (device is null) device = Device.getDevice();
-    if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
-    init_(device, fd);
-    if (device.tracking) device.new_Object(this);
+    super(device);
+    init_(fd);
+    init_();
 }
 
 /**
@@ -109,15 +110,14 @@
  * @since 2.1
  */
 public this(Device device, FontData[] fds) {
-    if (device is null) device = Device.getDevice();
-    if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
+    super(device);
     if (fds is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
     if (fds.length is 0) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
     for (int i=0; i<fds.length; i++) {
         if (fds[i] is null) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
     }
-    init_(device, fds[0]);
-    if (device.tracking) device.new_Object(this);
+    init_(fds[0]);
+    init_();
 }
 
 /**
@@ -143,33 +143,21 @@
  * </ul>
  */
 public this(Device device, String name, int height, int style) {
-    if (device is null) device = Device.getDevice();
-    if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
+    super(device);
     if (name is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
-    init_(device, new FontData (name, height, style));
-    if (device.tracking) device.new_Object(this);
+    init_(new FontData (name, height, style));
+    init_();
 }
 
 /*public*/ this(Device device, String name, float height, int style) {
-    if (device is null) device = Device.getDevice();
-    if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
+    super(device);
     if (name is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
-    init_(device, new FontData (name, height, style));
-    if (device.tracking) device.new_Object(this);
+    init_(new FontData (name, height, style));
+    init_();
 }
-
-/**
- * Disposes of the operating system resources associated with
- * the font. Applications must dispose of all fonts which
- * they allocate.
- */
-override public void dispose() {
-    if (handle is null) return;
-    if (device.isDisposed()) return;
+void destroy() {
     OS.DeleteObject(handle);
     handle = null;
-    if (device.tracking) device.dispose_Object(this);
-    device = null;
 }
 
 /**
@@ -223,9 +211,8 @@
     return cast(hash_t)handle;
 }
 
-void init_ (Device device, FontData fd) {
+void init_ (FontData fd) {
     if (fd is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
-    this.device = device;
     LOGFONT* logFont = &fd.data;
     int lfHeight = logFont.lfHeight;
     logFont.lfHeight = device.computePixels(fd.height);
@@ -274,10 +261,8 @@
  * @return a new font object containing the specified device and handle
  */
 public static Font win32_new(Device device, HFONT handle) {
-    if (device is null) device = Device.getDevice();
-    Font font = new Font();
+    Font font = new Font(device);
     font.handle = handle;
-    font.device = device;
     return font;
 }
 
--- a/dwt/graphics/GC.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/graphics/GC.d	Sat May 17 17:34:28 2008 +0200
@@ -73,6 +73,8 @@
 
 public final class GC : Resource {
 
+    alias Resource.init_ init_;
+
     /**
      * the handle to the OS device context
      * (Warning: This field is platform dependent)
@@ -181,7 +183,7 @@
     if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
     this.device = data.device = device;
     init_ (drawable, data, hDC);
-    if (device.tracking) device.new_Object(this);
+    init_();
 }
 
 static int checkStyle(int style) {
@@ -263,7 +265,7 @@
                 default:
             }
             if (dashes !is null) {
-                Gdip.Pen_SetDashPattern(pen, dashes, dashes.length);
+                Gdip.Pen_SetDashPattern(pen, dashes.ptr, dashes.length);
                 Gdip.Pen_SetDashStyle(pen, Gdip.DashStyleCustom);
                 Gdip.Pen_SetDashOffset(pen, dashOffset);
             } else {
@@ -323,25 +325,26 @@
             }
         }
         if ((state & FONT) !is 0) {
-            OS.SelectObject(handle, data.hFont);
-            auto font = createGdipFont(handle, data.hFont);
+            Font font = data.font;
+            OS.SelectObject(handle, font.handle);
+            auto gdipFont = createGdipFont(handle, font.handle);
             if (data.gdipFont !is null) Gdip.Font_delete(data.gdipFont);
-            data.gdipFont = font;
+            data.gdipFont = gdipFont;
         }
         if ((state & DRAW_OFFSET) !is 0) {
             data.gdipXOffset = data.gdipYOffset = 0;
             auto matrix = Gdip.Matrix_new(1, 0, 0, 1, 0, 0);
-            float[6] elements;
+            float[2] point; point[0]=1.0; point[1]=1.0;
             Gdip.Graphics_GetTransform(gdipGraphics, matrix);
-            Gdip.Matrix_GetElements(matrix, elements );
+            Gdip.Matrix_TransformPoints(matrix, cast(Gdip.PointF*)point.ptr, 1);
             Gdip.Matrix_delete(matrix);
-            float scaling = elements[0];
+            float scaling = point[0];
             if (scaling < 0) scaling = -scaling;
             float penWidth = data.lineWidth * scaling;
             if (penWidth is 0 || (cast(int)penWidth % 2) is 1) {
                 data.gdipXOffset = 0.5f / scaling;
             }
-            scaling = elements[3];
+            scaling = point[1];
             if (scaling < 0) scaling = -scaling;
             penWidth = data.lineWidth * scaling;
             if (penWidth is 0 || (cast(int)penWidth % 2) is 1) {
@@ -439,7 +442,8 @@
         OS.SetTextColor(handle, data.foreground);
     }
     if ((state & FONT) !is 0) {
-        OS.SelectObject(handle, data.hFont);
+        Font font = data.font;
+        OS.SelectObject(handle, font.handle);
     }
 }
 
@@ -627,11 +631,12 @@
  *    <li>ERROR_THREAD_INVALID_ACCESS if not called from the thread that created the drawable</li>
  * </ul>
  */
-override public void dispose() {
-    if (handle is null) return;
-    if (data.device.isDisposed()) return;
-
+void destroy() {
+    bool gdip = data.gdipGraphics !is null;
     disposeGdip();
+    if (gdip && (data.style & DWT.MIRRORED) !is 0) {
+        OS.SetLayout(handle, OS.GetLayout(handle) | OS.LAYOUT_RTL);
+    }
 
     /* Select stock pen and brush objects and free resources */
     if (data.hPen !is null) {
@@ -661,14 +666,11 @@
     /*
     * Dispose the HDC.
     */
-    Device device = data.device;
     if (drawable !is null) drawable.internal_dispose_GC(handle, data);
     drawable = null;
     handle = null;
     data.image = null;
     data.ps = null;
-    if (device.tracking) device.dispose_Object(this);
-    data.device = null;
     data = null;
 }
 
@@ -816,6 +818,7 @@
 public void drawFocus (int x, int y, int width, int height) {
     if (handle is null) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
     if ((data.uiState & OS.UISF_HIDEFOCUS) !is 0) return;
+    data.focusDrawn = true;
     HDC hdc = handle;
     int state = 0;
     auto gdipGraphics = data.gdipGraphics;
@@ -837,13 +840,11 @@
         Gdip.Graphics_GetTransform(gdipGraphics, matrix);
         if (!Gdip.Matrix_IsIdentity(matrix)) {
             gotElements = true;
-            Gdip.Matrix_GetElements(matrix, lpXform);
+            Gdip.Matrix_GetElements(matrix, lpXform.ptr);
         }
         Gdip.Matrix_delete(matrix);
         hdc = Gdip.Graphics_GetHDC(gdipGraphics);
         state = OS.SaveDC(hdc);
-        OS.SetBkColor(hdc, data.background);
-        OS.SetTextColor(hdc, data.foreground);
         if (gotElements) {
             OS.SetGraphicsMode(hdc, OS.GM_ADVANCED);
             OS.SetWorldTransform(hdc, cast(XFORM*)lpXform.ptr);
@@ -853,12 +854,16 @@
             OS.DeleteObject(clipRgn);
         }
     }
+    OS.SetBkColor(hdc, 0xFFFFFF);
+    OS.SetTextColor(hdc, 0x000000);
     RECT rect;
     OS.SetRect(&rect, x, y, x + width, y + height);
     OS.DrawFocusRect(hdc, &rect);
     if (gdipGraphics !is null) {
         OS.RestoreDC(hdc, state);
         Gdip.Graphics_ReleaseHDC(gdipGraphics, hdc);
+    } else {
+        data.state &= ~(BACKGROUND_TEXT | FOREGROUND_TEXT);
     }
 }
 
@@ -934,7 +939,7 @@
 void drawImage(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, bool simple) {
     if (data.gdipGraphics !is null) {
         //TODO - cache bitmap
-        int[] gdipImage = srcImage.createGdipImage();
+        int /*long*/ [] gdipImage = srcImage.createGdipImage();
         auto img = cast(Gdip.Image) gdipImage[0];
         int imgWidth = Gdip.Image_GetWidth(img);
         int imgHeight = Gdip.Image_GetHeight(img);
@@ -1426,7 +1431,8 @@
     }
     auto srcHdc = OS.CreateCompatibleDC(handle);
     auto oldSrcBitmap = OS.SelectObject(srcHdc, srcColor);
-    auto destHdc = handle, x = destX, y = destY;
+    auto destHdc = handle;
+    int x = destX, y = destY;
     HDC tempHdc;
     HBITMAP tempBitmap;
     HBITMAP oldTempBitmap;
@@ -1806,7 +1812,7 @@
     auto gdipGraphics = data.gdipGraphics;
     if (gdipGraphics !is null) {
         Gdip.Graphics_TranslateTransform(gdipGraphics, data.gdipXOffset, data.gdipYOffset, Gdip.MatrixOrderPrepend);
-        Gdip.Graphics_DrawPolygon(gdipGraphics, data.gdipPen, cast(Gdip.Point[])pointArray, pointArray.length/2);
+        Gdip.Graphics_DrawPolygon(gdipGraphics, data.gdipPen, cast(Gdip.Point*)pointArray.ptr, pointArray.length/2);
         Gdip.Graphics_TranslateTransform(gdipGraphics, -data.gdipXOffset, -data.gdipYOffset, Gdip.MatrixOrderPrepend);
         return;
     }
@@ -1851,7 +1857,7 @@
     auto gdipGraphics = data.gdipGraphics;
     if (gdipGraphics !is null) {
         Gdip.Graphics_TranslateTransform(gdipGraphics, data.gdipXOffset, data.gdipYOffset, Gdip.MatrixOrderPrepend);
-        Gdip.Graphics_DrawLines(gdipGraphics, data.gdipPen, cast(Gdip.Point[])pointArray, pointArray.length / 2);
+        Gdip.Graphics_DrawLines(gdipGraphics, data.gdipPen, cast(Gdip.Point*)pointArray.ptr, pointArray.length / 2);
         Gdip.Graphics_TranslateTransform(gdipGraphics, -data.gdipXOffset, -data.gdipYOffset, Gdip.MatrixOrderPrepend);
         return;
     }
@@ -1898,6 +1904,14 @@
     checkGC(DRAW);
     auto gdipGraphics = data.gdipGraphics;
     if (gdipGraphics !is null) {
+        if (width < 0) {
+            x = x + width;
+            width = -width;
+        }
+        if (height < 0) {
+            y = y + height;
+            height = -height;
+        }
         Gdip.Graphics_TranslateTransform(gdipGraphics, data.gdipXOffset, data.gdipYOffset, Gdip.MatrixOrderPrepend);
         Gdip.Graphics_DrawRectangle(gdipGraphics, data.gdipPen, x, y, width, height);
         Gdip.Graphics_TranslateTransform(gdipGraphics, -data.gdipXOffset, -data.gdipYOffset, Gdip.MatrixOrderPrepend);
@@ -2036,29 +2050,33 @@
         nah = 0 - nah;
 
     Gdip.Graphics_TranslateTransform(gdipGraphics, data.gdipXOffset, data.gdipYOffset, Gdip.MatrixOrderPrepend);
-    auto path = Gdip.GraphicsPath_new(Gdip.FillModeAlternate);
-    if (path is null) DWT.error(DWT.ERROR_NO_HANDLES);
-    if (nw > naw) {
-        if (nh > nah) {
-            Gdip.GraphicsPath_AddArc(path, nx + nw - naw, ny, naw, nah, 0, -90);
-            Gdip.GraphicsPath_AddArc(path, nx, ny, naw, nah, -90, -90);
-            Gdip.GraphicsPath_AddArc(path, nx, ny + nh - nah, naw, nah, -180, -90);
-            Gdip.GraphicsPath_AddArc(path, nx + nw - naw, ny + nh - nah, naw, nah, -270, -90);
+    if (naw is 0 || nah is 0) {
+        Gdip.Graphics_DrawRectangle(gdipGraphics, data.gdipPen, x, y, width, height);
+    } else {
+        auto path = Gdip.GraphicsPath_new(Gdip.FillModeAlternate);
+        if (path is null) DWT.error(DWT.ERROR_NO_HANDLES);
+        if (nw > naw) {
+            if (nh > nah) {
+                Gdip.GraphicsPath_AddArc(path, nx + nw - naw, ny, naw, nah, 0, -90);
+                Gdip.GraphicsPath_AddArc(path, nx, ny, naw, nah, -90, -90);
+                Gdip.GraphicsPath_AddArc(path, nx, ny + nh - nah, naw, nah, -180, -90);
+                Gdip.GraphicsPath_AddArc(path, nx + nw - naw, ny + nh - nah, naw, nah, -270, -90);
+            } else {
+                Gdip.GraphicsPath_AddArc(path, nx + nw - naw, ny, naw, nh, -270, -180);
+                Gdip.GraphicsPath_AddArc(path, nx, ny, naw, nh, -90, -180);
+            }
         } else {
-            Gdip.GraphicsPath_AddArc(path, nx + nw - naw, ny, naw, nh, -270, -180);
-            Gdip.GraphicsPath_AddArc(path, nx, ny, naw, nh, -90, -180);
+            if (nh > nah) {
+                Gdip.GraphicsPath_AddArc(path, nx, ny, nw, nah, 0, -180);
+                Gdip.GraphicsPath_AddArc(path, nx, ny + nh - nah, nw, nah, -180, -180);
+            } else {
+                Gdip.GraphicsPath_AddArc(path, nx, ny, nw, nh, 0, 360);
+            }
         }
-    } else {
-        if (nh > nah) {
-            Gdip.GraphicsPath_AddArc(path, nx, ny, nw, nah, 0, -180);
-            Gdip.GraphicsPath_AddArc(path, nx, ny + nh - nah, nw, nah, -180, -180);
-        } else {
-            Gdip.GraphicsPath_AddArc(path, nx, ny, nw, nh, 0, 360);
-        }
+        Gdip.GraphicsPath_CloseFigure(path);
+        Gdip.Graphics_DrawPath(gdipGraphics, pen, path);
+        Gdip.GraphicsPath_delete(path);
     }
-    Gdip.GraphicsPath_CloseFigure(path);
-    Gdip.Graphics_DrawPath(gdipGraphics, pen, path);
-    Gdip.GraphicsPath_delete(path);
     Gdip.Graphics_TranslateTransform(gdipGraphics, -data.gdipXOffset, -data.gdipYOffset, Gdip.MatrixOrderPrepend);
 }
 
@@ -2316,7 +2334,7 @@
         if ((data.style & DWT.MIRRORED) !is 0) formatFlags |= Gdip.StringFormatFlagsDirectionRightToLeft;
         Gdip.StringFormat_SetFormatFlags(format, formatFlags);
         float[] tabs = (flags & DWT.DRAW_TAB) !is 0 ? [ cast(float) measureSpace(data.gdipFont, format) * 8] : new float[1];
-        Gdip.StringFormat_SetTabStops(format, 0, tabs.length, tabs);
+        Gdip.StringFormat_SetTabStops(format, 0, tabs.length, tabs.ptr);
         int hotkeyPrefix = (flags & DWT.DRAW_MNEMONIC) !is 0 ? Gdip.HotkeyPrefixShow : Gdip.HotkeyPrefixNone;
         if ((flags & DWT.DRAW_MNEMONIC) !is 0 && (data.uiState & OS.UISF_HIDEACCEL) !is 0) hotkeyPrefix = Gdip.HotkeyPrefixHide;
         Gdip.StringFormat_SetHotkeyPrefix(format, hotkeyPrefix);
@@ -2768,7 +2786,7 @@
     checkGC(FILL);
     if (data.gdipGraphics !is null) {
         int mode = OS.GetPolyFillMode(handle) is OS.WINDING ? Gdip.FillModeWinding : Gdip.FillModeAlternate;
-        Gdip.Graphics_FillPolygon(data.gdipGraphics, data.gdipBrush, cast(Gdip.Point[])pointArray, pointArray.length / 2, mode);
+        Gdip.Graphics_FillPolygon(data.gdipGraphics, data.gdipBrush, cast(Gdip.Point*)pointArray.ptr, pointArray.length / 2, mode);
         return;
     }
     if ((data.style & DWT.MIRRORED) !is 0) {
@@ -2803,6 +2821,14 @@
     if (handle is null) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
     checkGC(FILL);
     if (data.gdipGraphics !is null) {
+        if (width < 0) {
+            x = x + width;
+            width = -width;
+        }
+        if (height < 0) {
+            y = y + height;
+            height = -height;
+        }
         Gdip.Graphics_FillRectangle(data.gdipGraphics, data.gdipBrush, x, y, width, height);
         return;
     }
@@ -2886,29 +2912,33 @@
     if (nah < 0)
         nah = 0 - nah;
 
-    auto path = Gdip.GraphicsPath_new(Gdip.FillModeAlternate);
-    if (path is null) DWT.error(DWT.ERROR_NO_HANDLES);
-    if (nw > naw) {
-        if (nh > nah) {
-            Gdip.GraphicsPath_AddArc(path, nx + nw - naw, ny, naw, nah, 0, -90);
-            Gdip.GraphicsPath_AddArc(path, nx, ny, naw, nah, -90, -90);
-            Gdip.GraphicsPath_AddArc(path, nx, ny + nh - nah, naw, nah, -180, -90);
-            Gdip.GraphicsPath_AddArc(path, nx + nw - naw, ny + nh - nah, naw, nah, -270, -90);
+    if (naw is 0 || nah is 0) {
+        Gdip.Graphics_FillRectangle(data.gdipGraphics, data.gdipBrush, x, y, width, height);
+    } else {
+        auto path = Gdip.GraphicsPath_new(Gdip.FillModeAlternate);
+        if (path is null) DWT.error(DWT.ERROR_NO_HANDLES);
+        if (nw > naw) {
+            if (nh > nah) {
+                Gdip.GraphicsPath_AddArc(path, nx + nw - naw, ny, naw, nah, 0, -90);
+                Gdip.GraphicsPath_AddArc(path, nx, ny, naw, nah, -90, -90);
+                Gdip.GraphicsPath_AddArc(path, nx, ny + nh - nah, naw, nah, -180, -90);
+                Gdip.GraphicsPath_AddArc(path, nx + nw - naw, ny + nh - nah, naw, nah, -270, -90);
+            } else {
+                Gdip.GraphicsPath_AddArc(path, nx + nw - naw, ny, naw, nh, -270, -180);
+                Gdip.GraphicsPath_AddArc(path, nx, ny, naw, nh, -90, -180);
+            }
         } else {
-            Gdip.GraphicsPath_AddArc(path, nx + nw - naw, ny, naw, nh, -270, -180);
-            Gdip.GraphicsPath_AddArc(path, nx, ny, naw, nh, -90, -180);
+            if (nh > nah) {
+                Gdip.GraphicsPath_AddArc(path, nx, ny, nw, nah, 0, -180);
+                Gdip.GraphicsPath_AddArc(path, nx, ny + nh - nah, nw, nah, -180, -180);
+            } else {
+                Gdip.GraphicsPath_AddArc(path, nx, ny, nw, nh, 0, 360);
+            }
         }
-    } else {
-        if (nh > nah) {
-            Gdip.GraphicsPath_AddArc(path, nx, ny, nw, nah, 0, -180);
-            Gdip.GraphicsPath_AddArc(path, nx, ny + nh - nah, nw, nah, -180, -180);
-        } else {
-            Gdip.GraphicsPath_AddArc(path, nx, ny, nw, nh, 0, 360);
-        }
+        Gdip.GraphicsPath_CloseFigure(path);
+        Gdip.Graphics_FillPath(gdipGraphics, brush, path);
+        Gdip.GraphicsPath_delete(path);
     }
-    Gdip.GraphicsPath_CloseFigure(path);
-    Gdip.Graphics_FillPath(gdipGraphics, brush, path);
-    Gdip.GraphicsPath_delete(path);
 }
 
 void flush () {
@@ -3269,7 +3299,7 @@
  */
 public Font getFont () {
     if (handle is null) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
-    return Font.win32_new(data.device, data.hFont);
+    return data.font;
 }
 
 /**
@@ -3666,15 +3696,34 @@
 Gdip.Matrix identity() {
     if ((data.style & DWT.MIRRORED) !is 0) {
         int width = 0;
-        Image image = data.image;
-        if (image !is null) {
+        int technology = OS.GetDeviceCaps(handle, OS.TECHNOLOGY);
+        if (technology is OS.DT_RASPRINTER) {
+            width = OS.GetDeviceCaps(handle, OS.PHYSICALWIDTH);
+        } else {
+            Image image = data.image;
+            if (image !is null) {
             BITMAP bm;
             OS.GetObject(image.handle, BITMAP.sizeof, &bm);
-            width = bm.bmWidth;
-        } else if (data.hwnd !is null) {
-            RECT rect;
-            OS.GetClientRect(data.hwnd, &rect);
-            width = rect.right - rect.left;
+                width = bm.bmWidth;
+            } else {
+                HWND hwnd;
+                static if( OS.IsWinCE ){
+                    hwnd = data.hwnd;
+                }
+                else{
+                    hwnd = OS.WindowFromDC(handle);
+                }
+                if (hwnd !is null) {
+                    RECT rect;
+                    OS.GetClientRect(hwnd, &rect);
+                    width = rect.right - rect.left;
+                } else {
+                    auto hBitmap = OS.GetCurrentObject(handle, OS.OBJ_BITMAP);
+                    BITMAP bm;
+                    OS.GetObject(hBitmap, BITMAP.sizeof, &bm);
+                    width = bm.bmWidth;
+                }
+            }
         }
         POINT pt;
         static if (!OS.IsWinCE) OS.GetWindowOrgEx (handle, &pt);
@@ -3697,11 +3746,11 @@
         data.background = OS.GetBkColor(hDC);
     }
     data.state &= ~(NULL_BRUSH | NULL_PEN);
-    auto hFont = data.hFont;
-    if (hFont !is null && hFont !is cast(HFONT)-1 ) {
+    Font font = data.font;
+    if (font !is null) {
         data.state &= ~FONT;
     } else {
-        data.hFont = OS.GetCurrentObject(hDC, OS.OBJ_FONT);
+        data.font = Font.win32_new(device, OS.GetCurrentObject(hDC, OS.OBJ_FONT));
     }
     auto hPalette = data.device.hPalette;
     if (hPalette !is null) {
@@ -3763,8 +3812,16 @@
  */
 public bool isClipped() {
     if (handle is null) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
+    auto gdipGraphics = data.gdipGraphics;
+    if (gdipGraphics !is null) {
+        auto rgn = Gdip.Region_new();
+        Gdip.Graphics_GetClip(data.gdipGraphics, rgn);
+        bool isInfinite = Gdip.Region_IsInfinite(rgn, gdipGraphics) !is 0;
+        Gdip.Region_delete(rgn);
+        return !isInfinite;
+    }
     auto region = OS.CreateRectRgn(0, 0, 0, 0);
-    auto result = OS.GetClipRgn(handle, region);
+    int result = OS.GetClipRgn(handle, region);
     OS.DeleteObject(region);
     return result > 0;
 }
@@ -4068,7 +4125,7 @@
         initGdip();
         int mode = OS.GetPolyFillMode(handle) is OS.WINDING ? Gdip.FillModeWinding : Gdip.FillModeAlternate;
         Gdip.GraphicsPath_SetFillMode(path.handle, mode);
-        Gdip.Graphics_SetClip(data.gdipGraphics, path.handle);
+        Gdip.Graphics_SetClipPath(data.gdipGraphics, path.handle);
     }
 }
 
@@ -4163,7 +4220,7 @@
 public void setFont (Font font) {
     if (handle is null) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
     if (font !is null && font.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
-    data.hFont = font !is null ? font.handle : data.device.systemFont;
+    data.font = font !is null ? font : data.device.systemFont;
     data.state &= ~FONT;
 }
 
@@ -4327,7 +4384,7 @@
                 DWT.error(DWT.ERROR_INVALID_ARGUMENT);
         }
     }
-    int cap = attributes.join;
+    int cap = attributes.cap;
     if (cap !is data.lineCap) {
         mask |= LINE_CAP;
         switch (cap) {
@@ -4800,7 +4857,7 @@
         if ((data.style & DWT.MIRRORED) !is 0) formatFlags |= Gdip.StringFormatFlagsDirectionRightToLeft;
         Gdip.StringFormat_SetFormatFlags(format, formatFlags);
         float[] tabs = (flags & DWT.DRAW_TAB) !is 0 ? [measureSpace(data.gdipFont, format) * 8] : new float[1];
-        Gdip.StringFormat_SetTabStops(format, 0, tabs.length, tabs);
+        Gdip.StringFormat_SetTabStops(format, 0, tabs.length, tabs.ptr);
         Gdip.StringFormat_SetHotkeyPrefix(format, (flags & DWT.DRAW_MNEMONIC) !is 0 ? Gdip.HotkeyPrefixShow : Gdip.HotkeyPrefixNone);
         Gdip.Graphics_MeasureString(data.gdipGraphics, buffer, length_, data.gdipFont, pt, format, bounds);
         Gdip.StringFormat_delete(format);
@@ -4876,6 +4933,13 @@
 public static GC win32_new(HDC hDC, GCData data) {
     GC gc = new GC();
     gc.device = data.device;
+    data.style |= DWT.LEFT_TO_RIGHT;
+    if (OS.WIN32_VERSION >= OS.VERSION (4, 10)) {
+        int flags = OS.GetLayout (hDC);
+        if ((flags & OS.LAYOUT_RTL) !is 0) {
+            data.style |= DWT.RIGHT_TO_LEFT | DWT.MIRRORED;
+        }
+    }
     gc.init_(null, data, hDC);
     return gc;
 }
--- a/dwt/graphics/GCData.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/graphics/GCData.d	Sat May 17 17:34:28 2008 +0200
@@ -19,6 +19,7 @@
 import dwt.graphics.Image;
 import dwt.graphics.Device;
 import dwt.graphics.Pattern;
+import dwt.graphics.Font;
 
 /**
  * Instances of this class are descriptions of GCs in terms
@@ -36,7 +37,7 @@
     public int style, state = -1;
     public int foreground = -1;
     public int background = -1;
-    public HFONT hFont;
+    public Font font;
     public Pattern foregroundPattern;
     public Pattern backgroundPattern;
     public int lineStyle = DWT.LINE_SOLID;
@@ -47,7 +48,6 @@
     public float[] lineDashes;
     public float lineMiterLimit = 10;
     public int alpha = 0xFF;
-    public int uiState = 0;
 
     public Image image;
     public HPEN hPen, hOldPen;
@@ -63,5 +63,7 @@
     public Gdip.SolidBrush gdipBgBrush;
     public Gdip.Font gdipFont;
     public float gdipXOffset, gdipYOffset;
+    public int uiState = 0;
+    public bool focusDrawn;
 }
 
--- a/dwt/graphics/Image.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/graphics/Image.d	Sat May 17 17:34:28 2008 +0200
@@ -88,6 +88,8 @@
 
 public final class Image : Resource, Drawable {
 
+    alias Resource.init_ init_;
+
     /**
      * specifies whether the receiver is a bitmap or an icon
      * (one of <code>DWT.BITMAP</code>, <code>DWT.ICON</code>)
@@ -156,7 +158,8 @@
 /**
  * Prevents uninitialized instances from being created outside the package.
  */
-this () {
+this (Device device) {
+    super(device);
 }
 
 /**
@@ -190,10 +193,9 @@
  * </ul>
  */
 public this(Device device, int width, int height) {
-    if (device is null) device = Device.getDevice();
-    if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
-    init_(device, width, height);
-    if (device.tracking) device.new_Object(this);
+    super(device);
+    init_(width, height);
+    init_();
 }
 
 /**
@@ -228,15 +230,14 @@
  * </ul>
  */
 public this(Device device, Image srcImage, int flag) {
-    if (device is null) device = Device.getDevice();
-    if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
-    this.device = device;
+    super(device);
+    device = this.device;
     if (srcImage is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
     if (srcImage.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
     Rectangle rect = srcImage.getBounds();
+    this.type = srcImage.type;
     switch (flag) {
         case DWT.IMAGE_COPY: {
-            this.type = srcImage.type;
             switch (type) {
                 case DWT.BITMAP:
                     /* Get the HDC for the device */
@@ -269,7 +270,7 @@
                     break;
                 case DWT.ICON:
                     static if (OS.IsWinCE) {
-                        init_(device, srcImage.data);
+                        init_(srcImage.data);
                     } else {
                         handle = OS.CopyImage(srcImage.handle, OS.IMAGE_ICON, rect.width, rect.height, 0);
                         if (handle is null) DWT.error(DWT.ERROR_NO_HANDLES);
@@ -278,8 +279,7 @@
                 default:
                     DWT.error(DWT.ERROR_INVALID_IMAGE);
             }
-            if (device.tracking) device.new_Object(this);
-            return;
+            break;
         }
         case DWT.IMAGE_DISABLE: {
             ImageData data = srcImage.getImageData();
@@ -337,9 +337,8 @@
                     offset++;
                 }
             }
-            init_ (device, newData);
-            if (device.tracking) device.new_Object(this);
-            return;
+            init_ (newData);
+            break;
         }
         case DWT.IMAGE_GRAY: {
             ImageData data = srcImage.getImageData();
@@ -402,13 +401,13 @@
                     }
                 }
             }
-            init_ (device, newData);
-            if (device.tracking) device.new_Object(this);
-            return;
+            init_ (newData);
+            break;
         }
         default:
             DWT.error(DWT.ERROR_INVALID_ARGUMENT);
     }
+    init_();
 }
 
 /**
@@ -442,11 +441,10 @@
  * </ul>
  */
 public this(Device device, Rectangle bounds) {
-    if (device is null) device = Device.getDevice();
-    if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
+    super(device);
     if (bounds is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
-    init_(device, bounds.width, bounds.height);
-    if (device.tracking) device.new_Object(this);
+    init_(bounds.width, bounds.height);
+    init_();
 }
 
 /**
@@ -468,10 +466,9 @@
  * </ul>
  */
 public this(Device device, ImageData data) {
-    if (device is null) device = Device.getDevice();
-    if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
-    init_(device, data);
-    if (device.tracking) device.new_Object(this);
+    super(device);
+    init_(data);
+    init_();
 }
 
 /**
@@ -500,16 +497,15 @@
  * </ul>
  */
 public this(Device device, ImageData source, ImageData mask) {
-    if (device is null) device = Device.getDevice();
-    if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
+    super(device);
     if (source is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
     if (mask is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
     if (source.width !is mask.width || source.height !is mask.height) {
         DWT.error(DWT.ERROR_INVALID_ARGUMENT);
     }
     mask = ImageData.convertMask(mask);
-    init_(device, this, source, mask);
-    if (device.tracking) device.new_Object(this);
+    init_(this.device, this, source, mask);
+    init_();
 }
 
 /**
@@ -561,10 +557,9 @@
  * </ul>
  */
 public this (Device device, InputStream stream) {
-    if (device is null) device = Device.getDevice();
-    if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
-    init_(device, new ImageData(stream));
-    if (device.tracking) device.new_Object(this);
+    super(device);
+    init_(new ImageData(stream));
+    init_();
 }
 
 /**
@@ -595,12 +590,22 @@
  * </ul>
  */
 public this (Device device, String filename) {
-    if (device is null) device = Device.getDevice();
-    if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
+    super(device);
+    device = this.device;
     if (filename is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
-    this.device = device;
+    bool gdip = true;
     try {
         device.checkGDIP();
+    } catch (DWTException e) {
+        gdip = false;
+    }
+    /*
+    * Bug in GDI+.  For some reason, Bitmap.LockBits() segment faults
+    * when loading GIF files in 64-bit Windows.  The fix is to not use
+    * GDI+ image loading in this case.
+    */
+    if (gdip && (void*).sizeof is 8 && filename.toLowerCase().endsWith(".gif")) gdip = false;
+    if (gdip) {
         int length = filename.length;
         char[] chars = new char[length+1];
         filename.getChars(0, length, chars, 0);
@@ -741,7 +746,7 @@
                                 ImageData img = new ImageData(width, height, depth, paletteData, scanlinePad, data);
                                 img.transparentPixel = transparentPixel;
                                 img.alphaData = alphaData;
-                                init_(device, img);
+                                init_(img);
                             }
                         }
                     }
@@ -753,9 +758,9 @@
                 return;
             }
         }
-    } catch (DWTException e) {}
-    init_(device, new ImageData(filename));
-    if(device.tracking) device.new_Object(this);
+    }
+    init_(new ImageData(filename));
+    init_();
 }
 
 /**
@@ -853,7 +858,7 @@
             offset += 4;
         }
     }
-    int pBits;
+    void* pBits;
     HBITMAP hDib = OS.CreateDIBSection(null, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS, &pBits, null, 0);
     if (hDib is null) DWT.error(DWT.ERROR_NO_HANDLES);
 
@@ -877,7 +882,7 @@
 // active, even though it might be unlikely given the short span of time that the
 // function has them stored in the int array.
 
-int[] createGdipImage() {
+int /*long*/ [] createGdipImage() {
     switch (type) {
         case DWT.BITMAP: {
             if (alpha !is -1 || alphaData !is null || transparentPixel !is -1) {
@@ -996,7 +1001,14 @@
             int imgHeight = hBitmap is iconInfo.hbmMask ? bm.bmHeight / 2 : bm.bmHeight;
             Gdip.Bitmap img;
             ubyte* pixels;
-            if (imgWidth > imgHeight) {
+            /*
+            * Bug in GDI+.  Bitmap_new() segments fault if the image width
+            * is greater than the image height.
+            *
+            * Note that it also fails to generated an appropriate alpha
+            * channel when the icon depth is 32.
+            */
+            if (imgWidth > imgHeight || bm.bmBitsPixel is 32) {
                 auto hDC = device.internal_new_GC(null);
                 auto srcHdc = OS.CreateCompatibleDC(hDC);
                 auto oldSrcBitmap = OS.SelectObject(srcHdc, hBitmap);
@@ -1013,12 +1025,14 @@
                 OS.MoveMemory(srcData.ptr, dibBM.bmBits, srcData.length);
                 OS.DeleteObject(memDib);
                 OS.SelectObject(srcHdc, iconInfo.hbmMask);
-                for (int y = 0, dp = 0; y < imgHeight; ++y) {
+                for (int y = 0, dp = 3; y < imgHeight; ++y) {
                     for (int x = 0; x < imgWidth; ++x) {
-                        if (OS.GetPixel(srcHdc, x, y) !is 0) {
-                            srcData[dp + 3] = cast(ubyte)0;
-                        } else {
-                            srcData[dp + 3] = cast(ubyte)0xFF;
+                        if (srcData[dp] is 0) {
+                            if (OS.GetPixel(srcHdc, x, y) !is 0) {
+                            srcData[dp] = cast(ubyte)0;
+                            } else {
+                            srcData[dp] = cast(ubyte)0xFF;
+                            }
                         }
                         dp += 4;
                     }
@@ -1043,14 +1057,7 @@
     return null;
 }
 
-/**
- * Disposes of the operating system resources associated with
- * the image. Applications must dispose of all images which
- * they allocate.
- */
-override public void dispose () {
-    if (handle is null) return;
-    if (device.isDisposed()) return;
+void destroy () {
     if (memGC !is null) memGC.dispose();
     if (type is DWT.ICON) {
         static if (OS.IsWinCE) data = null;
@@ -1060,8 +1067,6 @@
     }
     handle = null;
     memGC = null;
-    if (device.tracking) device.dispose_Object(this);
-    device = null;
 }
 
 /**
@@ -1579,11 +1584,10 @@
     return cast(hash_t)handle;
 }
 
-void init_(Device device, int width, int height) {
+void init_(int width, int height) {
     if (width <= 0 || height <= 0) {
         DWT.error (DWT.ERROR_INVALID_ARGUMENT);
     }
-    this.device = device;
     type = DWT.BITMAP;
     auto hDC = device.internal_new_GC(null);
     handle = OS.CreateCompatibleBitmap(hDC, width, height);
@@ -1644,8 +1648,8 @@
         bmi[offset + 11] = cast(byte)((blueMask & 0xFF) >> 0);
     }
 
-    int[1] pBits;
-    return OS.CreateDIBSection(null, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS, pBits.ptr, null, 0);
+    void* pBits;
+    return OS.CreateDIBSection(null, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS, &pBits, null, 0);
 }
 
 /**
@@ -1666,7 +1670,6 @@
 }
 
 static int[] init_(Device device, Image image, ImageData i) {
-    if (image !is null) image.device = device;
 
     /*
      * BUG in Windows 98:
@@ -1833,7 +1836,7 @@
     }
     OS.MoveMemory(pBits, data.ptr, data.length);
 
-    int[] result = null;
+    int /*long*/ [] result = null;
     if (i.getTransparencyType() is DWT.TRANSPARENCY_MASK) {
         /* Get the HDC for the device */
         auto hDC = device.internal_new_GC(null);
@@ -1969,7 +1972,7 @@
     imageData.maskData = mask.data;
     return init_(device, image, imageData);
 }
-void init_(Device device, ImageData i) {
+void init_(ImageData i) {
     if (i is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
     init_(device, this, i);
 }
@@ -2013,7 +2016,7 @@
         }
         data.device = device;
         data.image = this;
-        data.hFont = device.systemFont;
+        data.font = device.systemFont;
     }
     return imageDC;
 }
@@ -2144,11 +2147,9 @@
  * @return a new image object containing the specified device, type and handle
  */
 public static Image win32_new(Device device, int type, HGDIOBJ handle) {
-    if (device is null) device = Device.getDevice();
-    Image image = new Image();
+    Image image = new Image(device);
     image.type = type;
     image.handle = handle;
-    image.device = device;
     return image;
 }
 
--- a/dwt/graphics/ImageData.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/graphics/ImageData.d	Sat May 17 17:34:28 2008 +0200
@@ -290,7 +290,7 @@
  *
  * @exception IllegalArgumentException <ul>
  *    <li>ERROR_INVALID_ARGUMENT - if the width or height is negative, or if the depth is not
- *          one of 1, 2, 4, 8, 16, 24 or 32</li>
+ *          one of 1, 2, 4, 8, 16, 24 or 32, or the data array is too small to contain the image data</li>
  *    <li>ERROR_NULL_ARGUMENT - if the palette or data is null</li>
  *    <li>ERROR_CANNOT_BE_ZERO - if the scanlinePad is zero</li>
  * </ul>
@@ -445,6 +445,17 @@
 
     int bytesPerLine = (((width * depth + 7) / 8) + (scanlinePad - 1))
         / scanlinePad * scanlinePad;
+    
+    /*
+     * When the image is being loaded from a PNG, we need to use the theoretical minimum
+     * number of bytes per line to check whether there is enough data, because the actual
+     * number of bytes per line is calculated based on the given depth, which may be larger
+     * than the actual depth of the PNG.
+     */
+    int minBytesPerLine = type is DWT.IMAGE_PNG ? ((((width + 7) / 8) + 3) / 4) * 4 : bytesPerLine;
+    if (data !is null && data.length < minBytesPerLine * height) {
+        DWT.error(DWT.ERROR_INVALID_ARGUMENT);
+    }
     setAllFields(
         width,
         height,
--- a/dwt/graphics/Path.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/graphics/Path.d	Sat May 17 17:34:28 2008 +0200
@@ -50,6 +50,8 @@
  */
 public class Path : Resource {
 
+    alias Resource.init_ init_;
+
     /**
      * the OS resource for the Path
      * (Warning: This field is platform dependent)
@@ -87,13 +89,84 @@
  * @see #dispose()
  */
 public this (Device device) {
-    if (device is null) device = Device.getDevice();
-    if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
-    this.device = device;
-    device.checkGDIP();
+    super(device);
+    this.device.checkGDIP();
     handle = Gdip.GraphicsPath_new(Gdip.FillModeAlternate);
     if (handle is null) DWT.error(DWT.ERROR_NO_HANDLES);
-    if (device.tracking) device.new_Object(this);
+    init_();
+}
+
+/**
+ * Constructs a new Path that is a copy of <code>path</code>. If
+ * <code>flatness</code> is less than or equal to zero, an unflatten
+ * copy of the path is created. Otherwise, it specifies the maximum
+ * error between the path and its flatten copy. Smaller numbers give
+ * better approximation.
+ * <p>
+ * This operation requires the operating system's advanced
+ * graphics subsystem which may not be available on some
+ * platforms.
+ * </p>
+ *
+ * @param device the device on which to allocate the path
+ * @param path the path to make a copy
+ * @param flatness the flatness value
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the device is null and there is no current device</li>
+ *    <li>ERROR_NULL_ARGUMENT - if the path is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the path has been disposed</li>
+ * </ul>
+ * @exception DWTException <ul>
+ *    <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ * @exception DWTError <ul>
+ *    <li>ERROR_NO_HANDLES if a handle for the path could not be obtained</li>
+ * </ul>
+ *
+ * @see #dispose()
+ * @since 3.4
+ */
+public this (Device device, Path path, float flatness) {
+    super(device);
+    if (path is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
+    if (path.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
+    flatness = Math.max(0, flatness);
+    handle = Gdip.GraphicsPath_Clone(path.handle);
+    if (flatness !is 0) Gdip.GraphicsPath_Flatten(handle, null, flatness);
+    if (handle is null) DWT.error(DWT.ERROR_NO_HANDLES);
+    init_();
+}
+
+/**
+ * Constructs a new with the specifed PathData.
+ * <p>
+ * This operation requires the operating system's advanced
+ * graphics subsystem which may not be available on some
+ * platforms.
+ * </p>
+ *
+ * @param device the device on which to allocate the path
+ * @param data the data for the path
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the device is null and there is no current device</li>
+ *    <li>ERROR_NULL_ARGUMENT - if the data is null</li>
+ * </ul>
+ * @exception DWTException <ul>
+ *    <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
+ * </ul>
+ * @exception DWTError <ul>
+ *    <li>ERROR_NO_HANDLES if a handle for the path could not be obtained</li>
+ * </ul>
+ *
+ * @see #dispose()
+ * @since 3.4
+ */
+public this (Device device, PathData data) {
+    this(device);
+    if (data is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
+    init_(data);
 }
 
 /**
@@ -321,18 +394,9 @@
     Gdip.GraphicsPath_GetLastPoint(handle, currentPoint);
 }
 
-/**
- * Disposes of the operating system resources associated with
- * the Path. Applications must dispose of all Paths that
- * they allocate.
- */
-override public void dispose() {
-    if (handle is null) return;
-    if (device.isDisposed()) return;
+void destroy() {
     Gdip.GraphicsPath_delete(handle);
     handle = null;
-    if (device.tracking) device.dispose_Object(this);
-    device = null;
 }
 
 /**
@@ -400,8 +464,8 @@
     int count = Gdip.GraphicsPath_GetPointCount(handle);
     byte[] gdipTypes = new byte[count];
     float[] points = new float[count * 2];
-    Gdip.GraphicsPath_GetPathTypes(handle, gdipTypes, count);
-    Gdip.GraphicsPath_GetPathPoints(handle, cast(Gdip.PointF[])points, count);
+    Gdip.GraphicsPath_GetPathTypes(handle, gdipTypes.ptr, count);
+    Gdip.GraphicsPath_GetPathPoints(handle, cast(Gdip.PointF*)points.ptr, count);
     byte[] types = new byte[count * 2];
     int index = 0, typesIndex = 0;
     while (index < count) {
@@ -458,6 +522,33 @@
     Gdip.GraphicsPath_GetLastPoint(handle, currentPoint);
 }
 
+void init_(PathData data) {
+    byte[] types = data.types;
+    float[] points = data.points;
+    for (int i = 0, j = 0; i < types.length; i++) {
+        switch (types[i]) {
+            case DWT.PATH_MOVE_TO:
+                moveTo(points[j++], points[j++]);
+                break;
+            case DWT.PATH_LINE_TO:
+                lineTo(points[j++], points[j++]);
+                break;
+            case DWT.PATH_CUBIC_TO:
+                cubicTo(points[j++], points[j++], points[j++], points[j++], points[j++], points[j++]);
+                break;
+            case DWT.PATH_QUAD_TO:
+                quadTo(points[j++], points[j++], points[j++], points[j++]);
+                break;
+            case DWT.PATH_CLOSE:
+                close();
+                break;
+            default:
+                dispose();
+                DWT.error(DWT.ERROR_INVALID_ARGUMENT);
+        }
+    }
+}
+
 /**
  * Returns <code>true</code> if the Path has been disposed,
  * and <code>false</code> otherwise.
--- a/dwt/graphics/Pattern.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/graphics/Pattern.d	Sat May 17 17:34:28 2008 +0200
@@ -43,7 +43,7 @@
  * @since 3.1
  */
 public class Pattern : Resource {
-
+    alias Resource.init_ init_;
     /**
      * the OS resource for the Pattern
      * (Warning: This field is platform dependent)
@@ -82,14 +82,12 @@
  * @see #dispose()
  */
 public this(Device device, Image image) {
-    if (device is null) device = Device.getDevice();
-    if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
+    super(device);
     if (image is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
     if (image.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
-    this.device = device;
-    device.checkGDIP();
-    int[] gdipImage = image.createGdipImage();
-    auto img = cast(Gdip.Image)gdipImage[0];
+    this.device.checkGDIP();
+    int /*long*/[] gdipImage = image.createGdipImage();
+    auto img = cast(Gdip.Image) gdipImage[0];
     int width = Gdip.Image_GetWidth(img);
     int height = Gdip.Image_GetHeight(img);
     handle = cast(Gdip.Brush)Gdip.TextureBrush_new(img, Gdip.WrapModeTile, 0, 0, width, height);
@@ -99,7 +97,7 @@
         OS.HeapFree(hHeap, 0, cast(void*)gdipImage[1]);
     }
     if (handle is null) DWT.error(DWT.ERROR_NO_HANDLES);
-    if (device.tracking) device.new_Object(this);
+    init_();
 }
 
 /**
@@ -175,14 +173,12 @@
  * @since 3.2
  */
 public this(Device device, float x1, float y1, float x2, float y2, Color color1, int alpha1, Color color2, int alpha2) {
-    if (device is null) device = Device.getDevice();
-    if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
+    super(device);
     if (color1 is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
     if (color1.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
     if (color2 is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
     if (color2.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
-    this.device = device;
-    device.checkGDIP();
+    this.device.checkGDIP();
     auto colorRef1 = color1.handle;
     int rgb = ((colorRef1 >> 16) & 0xFF) | (colorRef1 & 0xFF00) | ((colorRef1 & 0xFF) << 16);
     auto foreColor = Gdip.Color_new((alpha1 & 0xFF) << 24 | rgb);
@@ -215,23 +211,16 @@
             f[0] = 0;
             f[1] = 0.5f;
             f[2] = 1;
-            Gdip.LinearGradientBrush_SetInterpolationColors( cast(Gdip.LinearGradientBrush)handle, c, f, 3);
+            Gdip.LinearGradientBrush_SetInterpolationColors( cast(Gdip.LinearGradientBrush)handle, c.ptr, f.ptr, 3);
             Gdip.Color_delete(midColor);
         }
         Gdip.Color_delete(backColor);
     }
     Gdip.Color_delete(foreColor);
-    if (device.tracking) device.new_Object(this);
+    init_();
 }
 
-/**
- * Disposes of the operating system resources associated with
- * the Pattern. Applications must dispose of all Patterns that
- * they allocate.
- */
-override public void dispose() {
-    if (handle is null) return;
-    if (device.isDisposed()) return;
+void destroy() {
     int type = Gdip.Brush_GetType(handle);
     switch (type) {
         case Gdip.BrushTypeSolidColor:
@@ -249,8 +238,6 @@
         default:
     }
     handle = null;
-    if (device.tracking) device.dispose_Object(this);
-    device = null;
 }
 
 /**
--- a/dwt/graphics/Region.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/graphics/Region.d	Sat May 17 17:34:28 2008 +0200
@@ -38,6 +38,7 @@
  */
 
 public final class Region : Resource {
+    alias Resource.init_ init_;
 
     /**
      * the OS resource for the region
@@ -82,12 +83,10 @@
  * @since 3.0
  */
 public this (Device device) {
-    if (device is null) device = Device.getDevice();
-    if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
-    this.device = device;
+    super(device);
     handle = OS.CreateRectRgn (0, 0, 0, 0);
     if (handle is null) DWT.error(DWT.ERROR_NO_HANDLES);
-    if (device.tracking) device.new_Object(this);
+    init_();
 }
 
 /**
@@ -97,7 +96,7 @@
  * @param handle the handle for the result
  */
 this(Device device, HRGN handle) {
-    this.device = device;
+    super(device);
     this.handle = handle;
 }
 
@@ -233,18 +232,9 @@
     return contains(pt.x, pt.y);
 }
 
-/**
- * Disposes of the operating system resources associated with
- * the region. Applications must dispose of all regions which
- * they allocate.
- */
-override public void dispose () {
-    if (handle is null) return;
-    if (device.isDisposed()) return;
+void destroy () {
     OS.DeleteObject(handle);
     handle = null;
-    if (device.tracking) device.dispose_Object(this);
-    device = null;
 }
 
 /**
--- a/dwt/graphics/Resource.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/graphics/Resource.d	Sat May 17 17:34:28 2008 +0200
@@ -44,12 +44,30 @@
      */
     Device device;
 
+this() {
+}
+
+this(Device device) {
+    if (device is null) device = Device.getDevice();
+    if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
+    this.device = device;
+}
+
+void destroy() {
+}
+
 /**
  * Disposes of the operating system resources associated with
  * this resource. Applications must dispose of all resources
  * which they allocate.
  */
-public abstract void dispose();
+public void dispose() {
+    if (device is null) return;
+    if (device.isDisposed()) return;
+    destroy();
+    if (device.tracking) device.dispose_Object(this);
+    device = null;
+}
 
 /**
  * Returns the <code>Device</code> where this resource was
@@ -65,6 +83,10 @@
     return device;
 }
 
+void init_() {
+    if (device.tracking) device.new_Object(this);
+}
+
 /**
  * Returns <code>true</code> if the resource has been disposed,
  * and <code>false</code> otherwise.
--- a/dwt/graphics/TextLayout.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/graphics/TextLayout.d	Sat May 17 17:34:28 2008 +0200
@@ -16,6 +16,7 @@
 import dwt.DWTException;
 import dwt.internal.Compatibility;
 import dwt.internal.gdip.Gdip;
+
 import dwt.internal.win32.OS;
 
 import dwt.graphics.Color;
@@ -51,6 +52,8 @@
  *  @since 3.0
  */
 public final class TextLayout : Resource {
+    alias Resource.init_ init_;
+
     Font font;
     String text, segmentsText;
     int lineSpacing;
@@ -63,6 +66,7 @@
     int[] tabs;
     int[] segments;
     StyleItem[] styles;
+    int stylesCount;
 
     StyleItem[] allRuns;
     StyleItem[][] runs;
@@ -89,6 +93,11 @@
         }
     }
 
+    /* IME has a copy of these constants */
+    static const int UNDERLINE_IME_DOT = 1 << 16;
+    static const int UNDERLINE_IME_DASH = 2 << 16;
+    static const int UNDERLINE_IME_THICK = 3 << 16;
+
     class StyleItem {
         TextStyle style;
         int start, length;
@@ -112,6 +121,8 @@
         int descent;
         int leading;
         int x;
+        int underlinePos, underlineThickness;
+        int strikeoutPos, strikeoutThickness;
 
         /* Justify info (malloc during computeRuns) */
         int* justify;
@@ -191,22 +202,21 @@
  */
 public this (Device device) {
     static_this();
-    if (device is null) device = Device.getDevice();
-    if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
-    this.device = device;
+    super(device);
     wrapWidth = ascent = descent = -1;
     lineSpacing = 0;
     orientation = DWT.LEFT_TO_RIGHT;
     styles = new StyleItem[2];
     styles[0] = new StyleItem();
     styles[1] = new StyleItem();
+    stylesCount = 2;
     text = ""; //$NON-NLS-1$
     void* ppv;
     OS.OleInitialize(null);
     if (OS.CoCreateInstance(CLSID_CMultiLanguage.ptr, null, OS.CLSCTX_INPROC_SERVER, IID_IMLangFontLink2.ptr, cast(void*)&ppv) is OS.S_OK) {
         mLangFontLink2 = ppv;
     }
-    if (device.tracking) device.new_Object(this);
+    init_();
 }
 
 void breakRun(StyleItem run) {
@@ -349,9 +359,15 @@
             if (start is 0 && i !is lineStart && !run.tab) {
                 run = allRuns[--i];
             } else  if (start <= 0 && i is lineStart) {
-                i = firstIndice;
-                run = allRuns[i];
-                start = Math.max(1, firstStart);
+                if (lineWidth is wrapWidth && firstIndice > 0) {
+                    i = firstIndice - 1;
+                    run = allRuns[i];
+                    start = run.length;
+                } else {
+                    i = firstIndice;
+                    run = allRuns[i];
+                    start = Math.max(1, firstStart);
+                }
             }
             breakRun(run);
             while (start < run.length) {
@@ -471,12 +487,7 @@
     if (gc is null) device.internal_dispose_GC(hDC, null);
 }
 
-/**
- * Disposes of the operating system resources associated with
- * the text layout. Applications must dispose of all allocated text layouts.
- */
-override public void dispose () {
-    if (device is null) return;
+void destroy () {
     freeRuns();
     font = null;
     text = null;
@@ -493,8 +504,6 @@
         mLangFontLink2 = null;
     }
     OS.OleUninitialize();
-    if (device.tracking) device.dispose_Object(this);
-    device = null;
 }
 
 /**
@@ -595,7 +604,7 @@
         Gdip.Matrix_delete(identity_);
         if (!Gdip.Matrix_IsIdentity(matrix)) {
             lpXform = new float[6];
-            Gdip.Matrix_GetElements(matrix, lpXform);
+            Gdip.Matrix_GetElements(matrix, lpXform.ptr);
         }
         Gdip.Matrix_delete(matrix);
         if ((data.style & DWT.MIRRORED) !is 0 && lpXform !is null) {
@@ -642,26 +651,26 @@
         selectionEnd = translateOffset(selectionEnd);
     }
     RECT rect;
-    void* selBrush;
-    void* selPen;
-    void* selBrushFg;
+    Gdip.Brush selBrush;
+    Gdip.Pen selPen;
+    Gdip.Brush selBrushFg;
 
     if (hasSelection || (flags & DWT.LAST_LINE_SELECTION) !is 0) {
         if (gdip) {
             auto bg = selectionBackground.handle;
             auto argb = ((alpha & 0xFF) << 24) | ((bg >> 16) & 0xFF) | (bg & 0xFF00) | ((bg & 0xFF) << 16);
             auto color = Gdip.Color_new(argb);
-            selBrush = Gdip.SolidBrush_new(color);
+            selBrush = cast(Gdip.Brush)Gdip.SolidBrush_new(color);
             Gdip.Color_delete(color);
             auto fg = selectionForeground.handle;
             argb = ((alpha & 0xFF) << 24) | ((fg >> 16) & 0xFF) | (fg & 0xFF00) | ((fg & 0xFF) << 16);
             color = Gdip.Color_new(argb);
-            selBrushFg = Gdip.SolidBrush_new(color);
-            selPen = Gdip.Pen_new( cast(Gdip.Brush)selBrushFg, 1);
+            selBrushFg = cast(Gdip.Brush)Gdip.SolidBrush_new(color);
+            selPen = cast(Gdip.Pen) Gdip.Pen_new( cast(Gdip.Brush)selBrushFg, 1);
             Gdip.Color_delete(color);
         } else {
-            selBrush = OS.CreateSolidBrush(selectionBackground.handle);
-            selPen = OS.CreatePen(OS.PS_SOLID, 1, selectionForeground.handle);
+            selBrush = cast(Gdip.Brush)OS.CreateSolidBrush(selectionBackground.handle);
+            selPen = cast(Gdip.Pen)OS.CreatePen(OS.PS_SOLID, 1, selectionForeground.handle);
         }
     }
     int offset = (orientation & DWT.RIGHT_TO_LEFT) !is 0 ? -1 : 0;
@@ -670,7 +679,7 @@
         int drawX = x + getLineIndent(line);
         int drawY = y + lineY[line];
         StyleItem[] lineRuns = runs[line];
-        int lineHeight = lineY[line+1] - lineY[line];
+        int lineHeight = lineY[line+1] - lineY[line] - lineSpacing;
         if (flags !is 0 && (hasSelection || (flags & DWT.LAST_LINE_SELECTION) !is 0)) {
             bool extents = false;
             if (line is runs.length - 1 && (flags & DWT.LAST_LINE_SELECTION) !is 0) {
@@ -691,21 +700,23 @@
                 if ((flags & DWT.FULL_SELECTION) !is 0) {
                     width = OS.IsWin95 ? 0x7FFF : 0x6FFFFFF;
                 } else {
-                    width = (lineHeight - lineSpacing) / 3;
+                    width = lineHeight / 3;
                 }
                 if (gdip) {
-                    Gdip.Graphics_FillRectangle(gdipGraphics, cast(Gdip.Brush)selBrush, drawX + lineWidth[line], drawY, width, lineHeight - lineSpacing);
+                    Gdip.Graphics_FillRectangle(gdipGraphics, cast(Gdip.Brush)selBrush, drawX + lineWidth[line], drawY, width, lineHeight);
                 } else {
                     OS.SelectObject(hdc, selBrush);
-                    OS.PatBlt(hdc, drawX + lineWidth[line], drawY, width, lineHeight - lineSpacing, OS.PATCOPY);
+                    OS.PatBlt(hdc, drawX + lineWidth[line], drawY, width, lineHeight, OS.PATCOPY);
                 }
             }
         }
         if (drawX > clip.x + clip.width) continue;
         if (drawX + lineWidth[line] < clip.x) continue;
         int baseline = Math.max(0, this.ascent);
+        int lineUnderlinePos = 0;
         for (int i = 0; i < lineRuns.length; i++) {
             baseline = Math.max(baseline, lineRuns[i].ascent);
+            lineUnderlinePos = Math.min(lineUnderlinePos, lineRuns[i].underlinePos);
         }
         int alignmentX = drawX;
         for (int i = 0; i < lineRuns.length; i++) {
@@ -718,26 +729,25 @@
                     bool fullSelection = hasSelection && selectionStart <= run.start && selectionEnd >= end;
                     if (fullSelection) {
                         if (gdip) {
-                            Gdip.Graphics_FillRectangle(gdipGraphics, cast(Gdip.Brush)selBrush, drawX, drawY, run.width, lineHeight - lineSpacing);
+                            Gdip.Graphics_FillRectangle(gdipGraphics, cast(Gdip.Brush)selBrush, drawX, drawY, run.width, lineHeight);
                         } else {
                             OS.SelectObject(hdc, selBrush);
-                            OS.PatBlt(hdc, drawX, drawY, run.width, lineHeight - lineSpacing, OS.PATCOPY);
+                            OS.PatBlt(hdc, drawX, drawY, run.width, lineHeight, OS.PATCOPY);
                         }
                     } else {
                         if (run.style !is null && run.style.background !is null) {
                             auto bg = run.style.background.handle;
-                            int drawRunY = drawY + (baseline - run.ascent);
                             if (gdip) {
                                 int argb = ((alpha & 0xFF) << 24) | ((bg >> 16) & 0xFF) | (bg & 0xFF00) | ((bg & 0xFF) << 16);
                                 auto color = Gdip.Color_new(argb);
                                 auto brush = Gdip.SolidBrush_new(color);
-                                Gdip.Graphics_FillRectangle(gdipGraphics, cast(Gdip.Brush)brush, drawX, drawRunY, run.width, run.ascent + run.descent);
+                                Gdip.Graphics_FillRectangle(gdipGraphics, cast(Gdip.Brush)brush, drawX, drawY, run.width, lineHeight);
                                 Gdip.Color_delete(color);
                                 Gdip.SolidBrush_delete(brush);
                             } else {
                                 auto hBrush = OS.CreateSolidBrush (bg);
                                 auto oldBrush = OS.SelectObject(hdc, hBrush);
-                                OS.PatBlt(hdc, drawX, drawRunY, run.width, run.ascent + run.descent, OS.PATCOPY);
+                                OS.PatBlt(hdc, drawX, drawY, run.width, lineHeight, OS.PATCOPY);
                                 OS.SelectObject(hdc, oldBrush);
                                 OS.DeleteObject(hBrush);
                             }
@@ -757,8 +767,13 @@
                             OS.ScriptCPtoX(selEnd, true, cChars, gGlyphs, run.clusters, run.visAttrs, advances, &run.analysis, &piX);
                             runX = (orientation & DWT.RIGHT_TO_LEFT) !is 0 ? run.width - piX : piX;
                             rect.right = drawX + runX;
-                            rect.bottom = drawY + lineHeight - lineSpacing;
+                            rect.bottom = drawY + lineHeight;
                             if (gdip) {
+                                if (rect.left > rect.right) {
+                                    int tmp = rect.left;
+                                    rect.left = rect.right;
+                                    rect.right = tmp;
+                                }
                                 Gdip.Graphics_FillRectangle(gdipGraphics, cast(Gdip.Brush)selBrush, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
                             } else {
                                 OS.SelectObject(hdc, selBrush);
@@ -770,6 +785,7 @@
             }
             drawX += run.width;
         }
+        RECT* borderClip = null;
         drawX = alignmentX;
         for (int i = 0; i < lineRuns.length; i++) {
             StyleItem run = lineRuns[i];
@@ -819,7 +835,7 @@
                             if ((type & OS.PT_CLOSEFIGURE) !is 0) newType |= Gdip.PathPointTypeCloseSubpath;
                             types[typeIndex] = cast(byte)newType;
                         }
-                        auto path = Gdip.GraphicsPath_new(cast(Gdip.Point[])points, types, count, Gdip.FillModeAlternate);
+                        auto path = Gdip.GraphicsPath_new(cast(Gdip.Point*)points.ptr, types.ptr, count, Gdip.FillModeAlternate);
                         if (path is null) DWT.error(DWT.ERROR_NO_HANDLES);
                         auto brush = foregroundBrush;
                         if (fullSelection) {
@@ -865,46 +881,31 @@
                             Gdip.Graphics_Restore(gdipGraphics, gstate2);
                         }
                         Gdip.Graphics_SetSmoothingMode(gdipGraphics, antialias);
-                        if (run.style !is null && (run.style.underline || run.style.strikeout)) {
-                            auto newPen = hasSelection ? cast(Gdip.Pen)selPen : Gdip.Pen_new(brush, 1);
-                            Gdip.Graphics_SetPixelOffsetMode(gdipGraphics, Gdip.PixelOffsetModeNone);
-                            if (run.style.underline) {
-                                int underlineY = drawY + baseline + 1 - run.style.rise;
-                                Gdip.Graphics_DrawLine(gdipGraphics, newPen, drawX, underlineY, drawX + run.width, underlineY);
-                            }
-                            if (run.style.strikeout) {
-                                int strikeoutY = drawRunY + run.leading + (run.ascent - run.style.rise) / 2;
-                                Gdip.Graphics_DrawLine(gdipGraphics, newPen, drawX, strikeoutY, drawX + run.width, strikeoutY);
-                            }
-                            if (cast(void*)newPen !is selPen) Gdip.Pen_delete(newPen);
-                            Gdip.Graphics_SetPixelOffsetMode(gdipGraphics, Gdip.PixelOffsetModeHalf);
-                        }
+                        drawLines(gdip, gdipGraphics, x, drawY + baseline, lineUnderlinePos, drawY + lineHeight, lineRuns, i, brush, null, alpha);
                         if (partialSelection) {
                             Gdip.Graphics_Restore(gdipGraphics, gstate);
                             gstate = Gdip.Graphics_Save(gdipGraphics);
                             Gdip.Graphics_SetClip(gdipGraphics, &gdipRect, Gdip.CombineModeIntersect);
                             Gdip.Graphics_SetSmoothingMode(gdipGraphics, textAntialias);
-                            Gdip.Graphics_FillPath(gdipGraphics, cast(Gdip.Brush)selBrushFg, path);
+                            if ((data.style & DWT.MIRRORED) !is 0) {
+                                gstate2 = Gdip.Graphics_Save(gdipGraphics);
+                                Gdip.Graphics_ScaleTransform(gdipGraphics, -1, 1, Gdip.MatrixOrderPrepend);
+                                Gdip.Graphics_TranslateTransform(gdipGraphics, -2 * drawX - run.width, 0, Gdip.MatrixOrderPrepend);
+                            }
+                            Gdip.Graphics_FillPath(gdipGraphics, selBrushFg, path);
+                            if ((data.style & DWT.MIRRORED) !is 0) {
+                                Gdip.Graphics_Restore(gdipGraphics, gstate2);
+                            }
                             Gdip.Graphics_SetSmoothingMode(gdipGraphics, antialias);
-                            if (run.style !is null && (run.style.underline || run.style.strikeout)) {
-                                Gdip.Graphics_SetPixelOffsetMode(gdipGraphics, Gdip.PixelOffsetModeNone);
-                                if (run.style.underline) {
-                                    int underlineY = drawY + baseline + 1 - run.style.rise;
-                                    Gdip.Graphics_DrawLine(gdipGraphics, cast(Gdip.Pen)selPen, rect.left, underlineY, rect.right, underlineY);
-                                }
-                                if (run.style.strikeout) {
-                                    int strikeoutY = drawRunY + run.leading + (run.ascent - run.style.rise) / 2;
-                                    Gdip.Graphics_DrawLine(gdipGraphics, cast(Gdip.Pen)selPen, rect.left, strikeoutY, rect.right, strikeoutY);
-                                }
-                                Gdip.Graphics_SetPixelOffsetMode(gdipGraphics, Gdip.PixelOffsetModeHalf);
-                            }
+                            drawLines(gdip, gdipGraphics, x, drawY + baseline, lineUnderlinePos, drawY + lineHeight, lineRuns, i, selBrushFg, &rect, alpha);
                             Gdip.Graphics_Restore(gdipGraphics, gstate);
                         }
+                        borderClip = drawBorder(gdip, gdipGraphics, x, drawY, lineHeight, foregroundBrush, selBrushFg, fullSelection, borderClip, partialSelection ? &rect : null, alpha, lineRuns, i, selectionStart, selectionEnd);
                         Gdip.GraphicsPath_delete(path);
                         if ( brush !is cast(Gdip.Brush)selBrushFg && brush !is cast(Gdip.Brush)foregroundBrush)
                             Gdip.SolidBrush_delete(cast(Gdip.SolidBrush)brush);
                     }   else {
-                            int fg = foreground;
+                            auto fg = foreground;
                             if (fullSelection) {
                                 fg = selectionForeground.handle;
                             } else {
@@ -912,40 +913,14 @@
                         }
                         OS.SetTextColor(hdc, fg);
                         OS.ScriptTextOut(hdc, run.psc, drawX + offset, drawRunY, 0, null, &run.analysis , null, 0, run.glyphs, run.glyphCount, run.advances, run.justify, run.goffsets);
-                        if (run.style !is null && (run.style.underline || run.style.strikeout)) {
-                            auto newPen = hasSelection && fg is selectionForeground.handle ? cast(HPEN)selPen : OS.CreatePen(OS.PS_SOLID, 1, fg);
-                            auto oldPen = OS.SelectObject(hdc, newPen);
-                            if (run.style.underline) {
-                                int underlineY = drawY + baseline + 1 - run.style.rise;
-                                OS.MoveToEx(hdc, drawX, underlineY, null);
-                                OS.LineTo(hdc, drawX + run.width, underlineY);
-                            }
-                            if (run.style.strikeout) {
-                                int strikeoutY = drawRunY + run.leading + (run.ascent - run.style.rise) / 2;
-                                OS.MoveToEx(hdc, drawX, strikeoutY, null);
-                                OS.LineTo(hdc, drawX + run.width, strikeoutY);
-                            }
-                            OS.SelectObject(hdc, oldPen);
-                            if (!hasSelection || fg !is selectionForeground.handle) OS.DeleteObject(newPen);
-                        }
+                        drawLines(gdip, hdc, x, drawY + baseline, lineUnderlinePos, drawY + lineHeight, lineRuns, i, cast(void*)fg, null, alpha);
                         if (partialSelection && fg !is selectionForeground.handle) {
                             OS.SetTextColor(hdc, selectionForeground.handle);
                             OS.ScriptTextOut(hdc, run.psc, drawX + offset, drawRunY, OS.ETO_CLIPPED, &rect, &run.analysis , null, 0, run.glyphs, run.glyphCount, run.advances, run.justify, run.goffsets);
-                            if (run.style !is null && (run.style.underline || run.style.strikeout)) {
-                                auto oldPen = OS.SelectObject(hdc, selPen);
-                                if (run.style.underline) {
-                                    int underlineY = drawY + baseline + 1 - run.style.rise;
-                                    OS.MoveToEx(hdc, rect.left, underlineY, null);
-                                    OS.LineTo(hdc, rect.right, underlineY);
-                                }
-                                if (run.style.strikeout) {
-                                    int strikeoutY = drawRunY + run.leading + (run.ascent - run.style.rise) / 2;
-                                    OS.MoveToEx(hdc, rect.left, strikeoutY, null);
-                                    OS.LineTo(hdc, rect.right, strikeoutY);
-                                }
-                                OS.SelectObject(hdc, oldPen);
-                            }
+                            drawLines(gdip, hdc, x, drawY + baseline, lineUnderlinePos, drawY + lineHeight, lineRuns, i, cast(void*)selectionForeground.handle, &rect, alpha);
                         }
+                        int selForeground = selectionForeground !is null ? selectionForeground.handle : 0;
+                        borderClip = drawBorder(gdip, hdc, x, drawY, lineHeight, cast(void*)foreground, cast(void*)selForeground, fullSelection, borderClip, partialSelection ? &rect : null, alpha, lineRuns, i, selectionStart, selectionEnd);
                     }
                 }
             }
@@ -955,7 +930,7 @@
     if (gdip) {
         if (selBrush !is null) Gdip.SolidBrush_delete(cast(Gdip.SolidBrush)selBrush);
         if (selBrushFg !is null) Gdip.SolidBrush_delete(cast(Gdip.SolidBrush)selBrushFg);
-        if (selPen !is null) Gdip.Pen_delete(cast(Gdip.Pen)selPen);
+        if (selPen !is null) Gdip.Pen_delete(selPen);
     } else {
         OS.RestoreDC(hdc, state);
         if (gdipGraphics !is null) Gdip.Graphics_ReleaseHDC(gdipGraphics, hdc);
@@ -964,6 +939,355 @@
     }
 }
 
+void drawLines(bool advance, void* graphics, int x, int lineBaseline, int lineUnderlinePos, int lineBottom, StyleItem[] line, int index, void* color, RECT* clipRect, int alpha) {
+    StyleItem run = line[index];
+    TextStyle style = run.style;
+    if (style is null) return;
+    if (!style.underline && !style.strikeout) return;
+    int runX = x + run.x;
+    int underlineY = lineBaseline - lineUnderlinePos;
+    int strikeoutY = lineBaseline - run.strikeoutPos;
+    if (advance) {
+        Gdip.Graphics_SetPixelOffsetMode(cast(Gdip.Graphics)graphics, Gdip.PixelOffsetModeNone);
+        auto brush = color;
+        if (style.underline) {
+            if (style.underlineColor !is null) {
+                int fg = style.underlineColor.handle;
+                int argb = ((alpha & 0xFF) << 24) | ((fg >> 16) & 0xFF) | (fg & 0xFF00) | ((fg & 0xFF) << 16);
+                auto gdiColor = Gdip.Color_new(argb);
+                brush = Gdip.SolidBrush_new(gdiColor);
+                Gdip.Color_delete(gdiColor);
+            }
+            switch (style.underlineStyle) {
+                case DWT.UNDERLINE_SQUIGGLE:
+                case DWT.UNDERLINE_ERROR: {
+                    int squigglyThickness = 1;
+                    int squigglyHeight = 2 * squigglyThickness;
+                    int squigglyY = Math.min(underlineY - squigglyHeight / 2, lineBottom - squigglyHeight - 1);
+                    int squigglyX = runX;
+                    for (int i = index; i > 0 && style.isAdherentUnderline(line[i - 1].style); i--) {
+                        squigglyX = x + line[i - 1].x;
+                    }
+                    int gstate = 0;
+                    if (clipRect is null) {
+                        gstate = Gdip.Graphics_Save(cast(Gdip.Graphics)graphics);
+                        Gdip.Rect gdipRect;
+                        gdipRect.X = runX;
+                        gdipRect.Y = squigglyY;
+                        gdipRect.Width = run.width + 1;
+                        gdipRect.Height = squigglyY + squigglyHeight + 1;
+                        Gdip.Graphics_SetClip(cast(Gdip.Graphics)graphics, &gdipRect, Gdip.CombineModeIntersect);
+                    }
+                    int[] points = computePolyline(squigglyX, squigglyY, runX + run.width, squigglyY + squigglyHeight);
+                    auto pen = Gdip.Pen_new(cast(Gdip.Brush)brush, squigglyThickness);
+                    Gdip.Graphics_DrawLines(cast(Gdip.Graphics)graphics, pen, cast(Gdip.Point*)points.ptr, points.length / 2);
+                    Gdip.Pen_delete(pen);
+                    if (gstate !is 0) Gdip.Graphics_Restore(cast(Gdip.Graphics)graphics, gstate);
+                    break;
+                }
+                case DWT.UNDERLINE_SINGLE:
+                    Gdip.Graphics_FillRectangle(cast(Gdip.Graphics)graphics, cast(Gdip.Brush)brush, runX, underlineY, run.width, run.underlineThickness);
+                    break;
+                case DWT.UNDERLINE_DOUBLE:
+                    Gdip.Graphics_FillRectangle(cast(Gdip.Graphics)graphics, cast(Gdip.Brush)brush, runX, underlineY, run.width, run.underlineThickness);
+                    Gdip.Graphics_FillRectangle(cast(Gdip.Graphics)graphics, cast(Gdip.Brush)brush, runX, underlineY + run.underlineThickness * 2, run.width, run.underlineThickness);
+                    break;
+                case UNDERLINE_IME_THICK:
+                    Gdip.Graphics_FillRectangle(cast(Gdip.Graphics)graphics, cast(Gdip.Brush)brush, runX - run.underlineThickness, underlineY, run.width, run.underlineThickness * 2);
+                    break;
+                case UNDERLINE_IME_DOT:
+                case UNDERLINE_IME_DASH: {
+                    auto pen = Gdip.Pen_new(cast(Gdip.Brush)brush, 1);
+                    int dashStyle = style.underlineStyle is UNDERLINE_IME_DOT ? Gdip.DashStyleDot : Gdip.DashStyleDash;
+                    Gdip.Pen_SetDashStyle(pen, dashStyle);
+                    Gdip.Graphics_DrawLine(cast(Gdip.Graphics)graphics, pen, runX, underlineY, runX + run.width, underlineY);
+                    Gdip.Pen_delete(pen);
+                    break;
+                }
+            }
+            if (brush !is color) Gdip.SolidBrush_delete(cast(Gdip.SolidBrush)brush);
+        }
+        if (style.strikeout) {
+            if (style.strikeoutColor !is null) {
+                int fg = style.strikeoutColor.handle;
+                int argb = ((alpha & 0xFF) << 24) | ((fg >> 16) & 0xFF) | (fg & 0xFF00) | ((fg & 0xFF) << 16);
+                auto gdiColor = Gdip.Color_new(argb);
+                brush = Gdip.SolidBrush_new(gdiColor);
+                Gdip.Color_delete(gdiColor);
+            }
+            Gdip.Graphics_FillRectangle(cast(Gdip.Graphics)graphics, cast(Gdip.Brush)brush, runX, strikeoutY, run.width, run.strikeoutThickness);
+            if (brush !is color) Gdip.SolidBrush_delete(cast(Gdip.SolidBrush)brush);
+        }
+        Gdip.Graphics_SetPixelOffsetMode(cast(Gdip.Graphics)graphics, Gdip.PixelOffsetModeHalf);
+    } else {
+        uint colorRefUnderline = cast(uint)color;
+        uint colorRefStrikeout = cast(uint)color;
+        int /*long*/ brushUnderline = 0;
+        int /*long*/ brushStrikeout = 0;
+        RECT rect;
+        if (style.underline) {
+            if (style.underlineColor !is null) {
+                colorRefUnderline = style.underlineColor.handle;
+            }
+            switch (style.underlineStyle) {
+                case DWT.UNDERLINE_SQUIGGLE:
+                case DWT.UNDERLINE_ERROR: {
+                    int squigglyThickness = 1;
+                    int squigglyHeight = 2 * squigglyThickness;
+                    int squigglyY = Math.min(underlineY - squigglyHeight / 2, lineBottom - squigglyHeight - 1);
+                    int squigglyX = runX;
+                    for (int i = index; i > 0 && style.isAdherentUnderline(line[i - 1].style); i--) {
+                        squigglyX = x + line[i - 1].x;
+                    }
+                    int state = OS.SaveDC(graphics);
+                    if (clipRect !is null) {
+                        OS.IntersectClipRect(graphics, clipRect.left, clipRect.top, clipRect.right, clipRect.bottom);
+                    } else {
+                        OS.IntersectClipRect(graphics, runX, squigglyY, runX + run.width + 1, squigglyY + squigglyHeight + 1);
+                    }
+                    int[] points = computePolyline(squigglyX, squigglyY, runX + run.width, squigglyY + squigglyHeight);
+                    auto pen = OS.CreatePen(OS.PS_SOLID, squigglyThickness, colorRefUnderline);
+                    auto oldPen = OS.SelectObject(graphics, pen);
+                    OS.Polyline(graphics, cast(POINT*)points.ptr, points.length / 2);
+                    int length_ = points.length;
+                    if (length_ >= 2 && squigglyThickness <= 1) {
+                        OS.SetPixel (graphics, points[length_ - 2], points[length_ - 1], colorRefUnderline);
+                    }
+                    OS.RestoreDC(graphics, state);
+                    OS.SelectObject(graphics, oldPen);
+                    OS.DeleteObject(pen);
+                    break;
+                }
+                case DWT.UNDERLINE_SINGLE:
+                    brushUnderline = cast(uint) OS.CreateSolidBrush(colorRefUnderline);
+                    OS.SetRect(&rect, runX, underlineY, runX + run.width, underlineY + run.underlineThickness);
+                    if (clipRect !is null) {
+                        rect.left = Math.max(rect.left, clipRect.left);
+                        rect.right = Math.min(rect.right, clipRect.right);
+                    }
+                    OS.FillRect(graphics, &rect, cast(void*)brushUnderline);
+                    break;
+                case DWT.UNDERLINE_DOUBLE:
+                    brushUnderline = cast(uint)OS.CreateSolidBrush(colorRefUnderline);
+                    OS.SetRect(&rect, runX, underlineY, runX + run.width, underlineY + run.underlineThickness);
+                    if (clipRect !is null) {
+                        rect.left = Math.max(rect.left, clipRect.left);
+                        rect.right = Math.min(rect.right, clipRect.right);
+                    }
+                    OS.FillRect(graphics, &rect, cast(void*)brushUnderline);
+                    OS.SetRect(&rect, runX, underlineY + run.underlineThickness * 2, runX + run.width, underlineY + run.underlineThickness * 3);
+                    if (clipRect !is null) {
+                        rect.left = Math.max(rect.left, clipRect.left);
+                        rect.right = Math.min(rect.right, clipRect.right);
+                    }
+                    OS.FillRect(graphics, &rect,  cast(void*)brushUnderline);
+                    break;
+                case UNDERLINE_IME_THICK:
+                    brushUnderline = cast(uint)OS.CreateSolidBrush(colorRefUnderline);
+                    OS.SetRect(&rect, runX, underlineY - run.underlineThickness, runX + run.width, underlineY + run.underlineThickness);
+                    if (clipRect !is null) {
+                        rect.left = Math.max(rect.left, clipRect.left);
+                        rect.right = Math.min(rect.right, clipRect.right);
+                    }
+                    OS.FillRect(graphics, &rect,  cast(void*)brushUnderline);
+                    break;
+                case UNDERLINE_IME_DASH:
+                case UNDERLINE_IME_DOT: {
+                    underlineY = lineBaseline + run.descent;
+                    int penStyle = style.underlineStyle is UNDERLINE_IME_DASH ? OS.PS_DASH : OS.PS_DOT;
+                    auto pen = OS.CreatePen(penStyle, 1, colorRefUnderline);
+                    auto oldPen = OS.SelectObject(graphics, pen);
+                    OS.SetRect(&rect, runX, underlineY, runX + run.width, underlineY + run.underlineThickness);
+                    if (clipRect !is null) {
+                        rect.left = Math.max(rect.left, clipRect.left);
+                        rect.right = Math.min(rect.right, clipRect.right);
+                    }
+                    OS.MoveToEx(graphics, rect.left, rect.top, null);
+                    OS.LineTo(graphics, rect.right, rect.top);
+                    OS.SelectObject(graphics, oldPen);
+                    OS.DeleteObject(pen);
+                    break;
+                }
+            }
+        }
+        if (style.strikeout) {
+            if (style.strikeoutColor !is null) {
+                colorRefStrikeout = style.strikeoutColor.handle;
+            }
+            if (brushUnderline !is 0 && colorRefStrikeout is colorRefUnderline) {
+                brushStrikeout = brushUnderline;
+            } else {
+                brushStrikeout = cast(int) OS.CreateSolidBrush(colorRefStrikeout);
+            }
+            OS.SetRect(&rect, runX, strikeoutY, runX + run.width, strikeoutY + run.strikeoutThickness);
+            if (clipRect !is null) {
+                rect.left = Math.max(rect.left, clipRect.left);
+                rect.right = Math.min(rect.right, clipRect.right);
+            }
+            OS.FillRect(graphics, &rect, cast(void*)brushStrikeout);
+        }
+        if (brushUnderline !is 0) OS.DeleteObject(cast(void*)brushUnderline);
+        if (brushStrikeout !is 0 && brushStrikeout !is brushUnderline) OS.DeleteObject(cast(void*)brushStrikeout);
+    }
+}
+
+RECT* drawBorder(bool advance, void* graphics, int x, int y, int lineHeight, void* color, void* selectionColor, bool fullSelection, RECT* clipRect, RECT* rect, int alpha, StyleItem[] line, int index, int selectionStart, int selectionEnd) {
+    StyleItem run = line[index];
+    TextStyle style = run.style;
+    if (style is null) return null;
+    if (style.borderStyle is DWT.NONE) return null;
+    if (rect !is null) {
+        if (clipRect is null) {
+            clipRect = new RECT ();
+            OS.SetRect(clipRect, -1, rect.top, -1, rect.bottom);
+        }
+        bool isRTL = (orientation & DWT.RIGHT_TO_LEFT) !is 0;
+        if (run.start <= selectionStart && selectionStart <= run.start + run.length) {
+            if (run.analysis.fRTL ^ isRTL) {
+                clipRect.right = rect.left;
+            } else {
+                clipRect.left = rect.left;
+            }
+        }
+        if (run.start <= selectionEnd && selectionEnd <= run.start + run.length) {
+            if (run.analysis.fRTL ^ isRTL) {
+                clipRect.left = rect.right;
+            } else {
+                clipRect.right = rect.right;
+            }
+        }
+    }
+    if (index + 1 >= line.length || !style.isAdherentBorder(line[index + 1].style)) {
+        int left = run.x;
+        for (int i = index; i > 0 && style.isAdherentBorder(line[i - 1].style); i--) {
+            left = line[i - 1].x;
+        }
+        if (advance) {
+            auto brush = color;
+            int customColor = -1;
+            if (style.borderColor !is null) {
+                customColor = style.borderColor.handle;
+            } else {
+                if (style.foreground !is null) {
+                    customColor = style.foreground.handle;
+                }
+                if (fullSelection && clipRect is null) {
+                    customColor = -1;
+                    brush = selectionColor;
+                }
+            }
+            if (customColor !is -1) {
+                int argb = ((alpha & 0xFF) << 24) | ((customColor >> 16) & 0xFF) | (customColor & 0xFF00) | ((customColor & 0xFF) << 16);
+                auto gdiColor = Gdip.Color_new(argb);
+                brush = Gdip.SolidBrush_new(gdiColor);
+                Gdip.Color_delete(gdiColor);
+            }
+            int lineWidth = 1;
+            int lineStyle = Gdip.DashStyleSolid;
+            switch (style.borderStyle) {
+                case DWT.BORDER_SOLID: break;
+                case DWT.BORDER_DASH: lineStyle = Gdip.DashStyleDash; break;
+                case DWT.BORDER_DOT: lineStyle = Gdip.DashStyleDot; break;
+            }
+            auto pen = Gdip.Pen_new(cast(Gdip.Brush)brush, lineWidth);
+            Gdip.Pen_SetDashStyle(pen, lineStyle);
+            float gdipXOffset = 0.5f, gdipYOffset = 0.5f;
+            Gdip.Graphics_TranslateTransform(cast(Gdip.Graphics)graphics, gdipXOffset, gdipYOffset, Gdip.MatrixOrderPrepend);
+            if (style.borderColor is null && clipRect !is null) {
+                int gstate = Gdip.Graphics_Save(cast(Gdip.Graphics)graphics);
+                if (clipRect.left is -1) clipRect.left = 0;
+                if (clipRect.right is -1) clipRect.right = 0x7ffff;
+                Gdip.Rect gdipRect;
+                gdipRect.X = clipRect.left;
+                gdipRect.Y = clipRect.top;
+                gdipRect.Width = clipRect.right - clipRect.left;
+                gdipRect.Height = clipRect.bottom - clipRect.top;
+                Gdip.Graphics_SetClip(cast(Gdip.Graphics)graphics, &gdipRect, Gdip.CombineModeExclude);
+                Gdip.Graphics_DrawRectangle(cast(Gdip.Graphics)graphics, pen, x + left, y, run.x + run.width - left - 1, lineHeight - 1);
+                Gdip.Graphics_Restore(cast(Gdip.Graphics)graphics, gstate);
+                gstate = Gdip.Graphics_Save(cast(Gdip.Graphics)graphics);
+                Gdip.Graphics_SetClip(cast(Gdip.Graphics)graphics, &gdipRect, Gdip.CombineModeIntersect);
+                auto selPen = Gdip.Pen_new(cast(Gdip.Brush)selectionColor, lineWidth);
+                Gdip.Pen_SetDashStyle(pen, lineStyle);
+                Gdip.Graphics_DrawRectangle(cast(Gdip.Graphics)graphics, selPen, x + left, y, run.x + run.width - left - 1, lineHeight - 1);
+                Gdip.Pen_delete(selPen);
+                Gdip.Graphics_Restore(cast(Gdip.Graphics)graphics, gstate);
+            } else {
+                Gdip.Graphics_DrawRectangle(cast(Gdip.Graphics)graphics, pen, x + left, y, run.x + run.width - left - 1, lineHeight - 1);
+            }
+            Gdip.Graphics_TranslateTransform(cast(Gdip.Graphics)graphics, -gdipXOffset, -gdipYOffset, Gdip.MatrixOrderPrepend);
+            Gdip.Pen_delete(pen);
+            if (customColor !is -1) Gdip.SolidBrush_delete(cast(Gdip.SolidBrush)brush);
+        } else {
+            if (style.borderColor !is null) {
+                color = cast(void*)style.borderColor.handle;
+            } else {
+                if (style.foreground !is null) {
+                    color = cast(void*)style.foreground.handle;
+                }
+                if (fullSelection && clipRect is null) {
+                    color = selectionColor;
+                }
+            }
+            int lineWidth = 1;
+            int lineStyle = OS.PS_SOLID;
+            switch (style.borderStyle) {
+                case DWT.BORDER_SOLID: break;
+                case DWT.BORDER_DASH: lineStyle = OS.PS_DASH; break;
+                case DWT.BORDER_DOT: lineStyle = OS.PS_DOT; break;
+            }
+            LOGBRUSH logBrush;
+            logBrush.lbStyle = OS.BS_SOLID;
+            logBrush.lbColor = cast(uint)color;
+            auto newPen = OS.ExtCreatePen(lineStyle | OS.PS_GEOMETRIC, Math.max(1, lineWidth), &logBrush, 0, null);
+            auto oldPen = OS.SelectObject(graphics, newPen);
+            auto oldBrush = OS.SelectObject(graphics, OS.GetStockObject(OS.NULL_BRUSH));
+            OS.Rectangle(graphics, x + left, y, x + run.x + run.width, y + lineHeight);
+            if (style.borderColor is null && clipRect !is null && color !is selectionColor) {
+                int state = OS.SaveDC(graphics);
+                if (clipRect.left is -1) clipRect.left = 0;
+                if (clipRect.right is -1) clipRect.right = 0x7ffff;
+                OS.IntersectClipRect(graphics, clipRect.left, clipRect.top, clipRect.right, clipRect.bottom);
+                logBrush.lbColor = cast(uint)selectionColor;
+                auto selPen = OS.ExtCreatePen (lineStyle | OS.PS_GEOMETRIC, Math.max(1, lineWidth), &logBrush, 0, null);
+                OS.SelectObject(graphics, selPen);
+                OS.Rectangle(graphics, x + left, y, x + run.x + run.width, y + lineHeight);
+                OS.RestoreDC(graphics, state);
+                OS.SelectObject(graphics, newPen);
+                OS.DeleteObject(selPen);
+            }
+            OS.SelectObject(graphics, oldBrush);
+            OS.SelectObject(graphics, oldPen);
+            OS.DeleteObject(newPen);
+        }
+        return null;
+    }
+    return clipRect;
+}
+
+int[] computePolyline(int left, int top, int right, int bottom) {
+    int height = bottom - top; // can be any number
+    int width = 2 * height; // must be even
+    int peaks = Compatibility.ceil(right - left, width);
+    if (peaks is 0 && right - left > 2) {
+        peaks = 1;
+    }
+    int length_ = ((2 * peaks) + 1) * 2;
+    if (length_ < 0) return new int[0];
+
+    int[] coordinates = new int[length_];
+    for (int i = 0; i < peaks; i++) {
+        int index = 4 * i;
+        coordinates[index] = left + (width * i);
+        coordinates[index+1] = bottom;
+        coordinates[index+2] = coordinates[index] + width / 2;
+        coordinates[index+3] = top;
+    }
+    coordinates[length_-2] = left + (width * peaks);
+    coordinates[length_-1] = bottom;
+    return coordinates;
+}
+
 void freeRuns () {
     if (allRuns is null) return;
     for (int i=0; i<allRuns.length; i++) {
@@ -1011,13 +1335,18 @@
 }
 
 /**
- * Returns the bounds of the receiver.
+ * Returns the bounds of the receiver. The width returned is either the
+ * width of the longest line or the width set using {@link TextLayout#setWidth(int)}.
+ * To obtain the text bounds of a line use {@link TextLayout#getLineBounds(int)}.
  *
  * @return the bounds of the receiver
  *
  * @exception DWTException <ul>
  *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
  * </ul>
+ *
+ * @see #setWidth(int)
+ * @see #getLineBounds(int)
  */
 public Rectangle getBounds () {
     checkLayout();
@@ -1050,11 +1379,11 @@
 public Rectangle getBounds (int start, int end) {
     checkLayout();
     computeRuns(null);
-    int length = text.length;
-    if (length is 0) return new Rectangle(0, 0, 0, 0);
+    int length_ = text.length;
+    if (length_ is 0) return new Rectangle(0, 0, 0, 0);
     if (start > end) return new Rectangle(0, 0, 0, 0);
-    start = Math.min(Math.max(0, start), length - 1);
-    end = Math.min(Math.max(0, end), length - 1);
+    start = Math.min(Math.max(0, start), length_ - 1);
+    end = Math.min(Math.max(0, end), length_ - 1);
     start = translateOffset(start);
     end = translateOffset(end);
     int left = 0x7fffffff, right = 0;
@@ -1187,7 +1516,7 @@
     if (this.font !is null) {
         return this.font.handle;
     }
-    return device.systemFont;
+    return device.systemFont.handle;
 }
 
 /**
@@ -1207,8 +1536,8 @@
 public int getLevel (int offset) {
     checkLayout();
     computeRuns(null);
-    int length = text.length;
-    if (!(0 <= offset && offset <= length)) DWT.error(DWT.ERROR_INVALID_RANGE);
+    int length_ = text.length;
+    if (!(0 <= offset && offset <= length_)) DWT.error(DWT.ERROR_INVALID_RANGE);
     offset = translateOffset(offset);
     for (int i=1; i<allRuns.length; i++) {
         if (allRuns[i].start > offset) {
@@ -1306,8 +1635,8 @@
 public int getLineIndex (int offset) {
     checkLayout();
     computeRuns(null);
-    int length = text.length;
-    if (!(0 <= offset && offset <= length)) DWT.error(DWT.ERROR_INVALID_RANGE);
+    int length_ = text.length;
+    if (!(0 <= offset && offset <= length_)) DWT.error(DWT.ERROR_INVALID_RANGE);
     offset = translateOffset(offset);
     for (int line=0; line<runs.length; line++) {
         if (lineOffset[line + 1] > offset) {
@@ -1337,7 +1666,7 @@
     auto hDC = device.internal_new_GC(null);
     auto srcHdc = OS.CreateCompatibleDC(hDC);
     TEXTMETRIC lptm;
-    OS.SelectObject(srcHdc, font !is null ? font.handle : device.systemFont);
+    OS.SelectObject(srcHdc, font !is null ? font.handle : device.systemFont.handle);
     OS.GetTextMetrics(srcHdc, &lptm);
     OS.DeleteDC(srcHdc);
     device.internal_dispose_GC(hDC, null);
@@ -1404,53 +1733,47 @@
 public Point getLocation (int offset, bool trailing) {
     checkLayout();
     computeRuns(null);
-    int length = text.length;
-    if (!(0 <= offset && offset <= length)) DWT.error(DWT.ERROR_INVALID_RANGE);
-    length = segmentsText.length;
+    int length_ = text.length;
+    if (!(0 <= offset && offset <= length_)) DWT.error(DWT.ERROR_INVALID_RANGE);
+    length_ = segmentsText.length;
     offset = translateOffset(offset);
     int line;
     for (line=0; line<runs.length; line++) {
         if (lineOffset[line + 1] > offset) break;
     }
     line = Math.min(line, runs.length - 1);
-    StyleItem[] lineRuns = runs[line];
-    Point result = null;
-    if (offset is length) {
-        result = new Point(lineWidth[line], lineY[line]);
-    } else {
-        int width = 0;
-        for (int i=0; i<lineRuns.length; i++) {
-            StyleItem run = lineRuns[i];
-            int end = run.start + run.length;
-            if (run.start <= offset && offset < end) {
-                if (run.style !is null && run.style.metrics !is null) {
-                    GlyphMetrics metrics = run.style.metrics;
-                    width += metrics.width * (offset - run.start + (trailing ? 1 : 0));
-                    result = new Point(width, lineY[line]);
-                } else if (run.tab) {
-                    if (trailing || (offset is length)) width += run.width;
-                    result = new Point(width, lineY[line]);
-                } else {
-                    int runOffset = offset - run.start;
-                    int cChars = run.length;
-                    int gGlyphs = run.glyphCount;
-                    int piX;
-                    int* advances = run.justify !is null ? run.justify : run.advances;
-                    OS.ScriptCPtoX(runOffset, trailing, cChars, gGlyphs, run.clusters, run.visAttrs, advances, &run.analysis, &piX);
-                    if ((orientation & DWT.RIGHT_TO_LEFT) !is 0) {
-                        result = new Point(width + (run.width - piX), lineY[line]);
-                    } else {
-                        result = new Point(width + piX, lineY[line]);
-                    }
-                }
-                break;
+    if (offset is length_) {
+        return new Point(getLineIndent(line) + lineWidth[line], lineY[line]);
+    }
+    int low = -1;
+    int high = allRuns.length;
+    while (high - low > 1) {
+        int index = ((high + low) / 2);
+        StyleItem run = allRuns[index];
+        if (run.start > offset) {
+            high = index;
+        } else if (run.start + run.length <= offset) {
+            low = index;
+        } else {
+            int width;
+            if (run.style !is null && run.style.metrics !is null) {
+                GlyphMetrics metrics = run.style.metrics;
+                width = metrics.width * (offset - run.start + (trailing ? 1 : 0));
+            } else if (run.tab) {
+                width = (trailing || (offset is length_)) ? run.width : 0;
+            } else {
+                int runOffset = offset - run.start;
+                int cChars = run.length;
+                int gGlyphs = run.glyphCount;
+                int piX;
+                int* advances = run.justify !is null ? run.justify : run.advances;
+                OS.ScriptCPtoX(runOffset, trailing, cChars, gGlyphs, run.clusters, run.visAttrs, advances, &run.analysis, &piX);
+                width = (orientation & DWT.RIGHT_TO_LEFT) !is 0 ? run.width - piX : piX;
             }
-            width += run.width;
+            return new Point(run.x + width, lineY[line]);
         }
     }
-    if (result is null) result = new Point(0, 0);
-    result.x += getLineIndent(line);
-    return result;
+    return new Point(0, 0);
 }
 
 /**
@@ -1479,13 +1802,13 @@
 
 int _getOffset(int offset, int movement, bool forward) {
     computeRuns(null);
-    int length = text.length;
-    if (!(0 <= offset && offset <= length)) DWT.error(DWT.ERROR_INVALID_RANGE);
-    if (forward && offset is length) return length;
+    int length_ = text.length;
+    if (!(0 <= offset && offset <= length_)) DWT.error(DWT.ERROR_INVALID_RANGE);
+    if (forward && offset is length_) return length_;
     if (!forward && offset is 0) return 0;
     int step = forward ? 1 : -1;
     if ((movement & DWT.MOVEMENT_CHAR) !is 0) return offset + step;
-    length = segmentsText.length;
+    length_ = segmentsText.length;
     offset = translateOffset(offset);
     SCRIPT_LOGATTR* logAttr;
     SCRIPT_PROPERTIES* properties;
@@ -1545,7 +1868,7 @@
             }
         }
         i += step;
-    } while (0 <= i && i < allRuns.length - 1 && 0 <= offset && offset < length);
+    } while (0 <= i && i < allRuns.length - 1 && 0 <= offset && offset < length_);
     return forward ? text.length : 0;
 }
 
@@ -1611,16 +1934,22 @@
         if (lineY[line + 1] > y) break;
     }
     line = Math.min(line, runs.length - 1);
-    x -= getLineIndent(line);
     StyleItem[] lineRuns = runs[line];
-    if (x >= lineWidth[line]) x = lineWidth[line] - 1;
-    if (x < 0) x = 0;
-    int width = 0;
-    for (int i = 0; i < lineRuns.length; i++) {
-        StyleItem run = lineRuns[i];
-        if (run.lineBreak && !run.softBreak) return untranslateOffset(run.start);
-        if (width + run.width > x) {
-            int xRun = x - width;
+    int lineIndent = getLineIndent(line);
+    if (x >= lineIndent + lineWidth[line]) x = lineIndent + lineWidth[line] - 1;
+    if (x < lineIndent) x = lineIndent;
+    int low = -1;
+    int high = lineRuns.length;
+    while (high - low > 1) {
+        int index = ((high + low) / 2);
+        StyleItem run = lineRuns[index];
+        if (run.x > x) {
+            high = index;
+        } else if (run.x + run.width <= x) {
+            low = index;
+        } else {
+            if (run.lineBreak && !run.softBreak) return untranslateOffset(run.start);
+            int xRun = x - run.x;
             if (run.style !is null && run.style.metrics !is null) {
                 GlyphMetrics metrics = run.style.metrics;
                 if (metrics.width > 0) {
@@ -1631,7 +1960,7 @@
                 }
             }
             if (run.tab) {
-                if (trailing !is null) trailing[0] = x < (width + run.width / 2) ? 0 : 1;
+                if (trailing !is null) trailing[0] = x < (run.x + run.width / 2) ? 0 : 1;
                 return untranslateOffset(run.start);
             }
             int cChars = run.length;
@@ -1646,7 +1975,6 @@
             if (trailing !is null) trailing[0] = piTrailing;
             return untranslateOffset(run.start + piCP);
         }
-        width += run.width;
     }
     if (trailing !is null) trailing[0] = 0;
     return untranslateOffset(lineOffset[line + 1]);
@@ -1706,9 +2034,9 @@
  */
 public int[] getRanges () {
     checkLayout();
-    int[] result = new int[styles.length * 2];
+    int[] result = new int[stylesCount * 2];
     int count = 0;
-    for (int i=0; i<styles.length - 1; i++) {
+    for (int i=0; i<stylesCount - 1; i++) {
         if (styles[i].style !is null) {
             result[count++] = styles[i].start;
             result[count++] = styles[i + 1].start - 1;
@@ -1740,17 +2068,17 @@
     if (segments is null) return text;
     int nSegments = segments.length;
     if (nSegments <= 1) return text;
-    int length = text.length;
-    if (length is 0) return text;
+    int length_ = text.length;
+    if (length_ is 0) return text;
     if (nSegments is 2) {
-        if (segments[0] is 0 && segments[1] is length) return text;
+        if (segments[0] is 0 && segments[1] is length_) return text;
     }
-    char[] oldChars = new char[length];
-    text.getChars(0, length, oldChars, 0);
-    char[] newChars = new char[length + nSegments];
+    char[] oldChars = new char[length_];
+    text.getChars(0, length_, oldChars, 0);
+    char[] newChars = new char[length_ + nSegments];
     int charCount = 0, segmentCount = 0;
     wchar separator = orientation is DWT.RIGHT_TO_LEFT ? RTL_MARK : LTR_MARK;
-    while (charCount < length) {
+    while (charCount < length_) {
         if (segmentCount < nSegments && charCount is segments[segmentCount]) {
             newChars[charCount + segmentCount++] = separator;
         } else {
@@ -1793,9 +2121,9 @@
  */
 public TextStyle getStyle (int offset) {
     checkLayout();
-    int length = text.length;
-    if (!(0 <= offset && offset < length)) DWT.error(DWT.ERROR_INVALID_RANGE);
-    for (int i=1; i<styles.length; i++) {
+    int length_ = text.length;
+    if (!(0 <= offset && offset < length_)) DWT.error(DWT.ERROR_INVALID_RANGE);
+    for (int i=1; i<stylesCount; i++) {
         if (styles[i].start > offset) {
             return styles[i - 1].style;
         }
@@ -1818,9 +2146,9 @@
  */
 public TextStyle[] getStyles () {
     checkLayout();
-    TextStyle[] result = new TextStyle[styles.length];
+    TextStyle[] result = new TextStyle[stylesCount];
     int count = 0;
-    for (int i=0; i<styles.length; i++) {
+    for (int i=0; i<stylesCount; i++) {
         if (styles[i].style !is null) {
             result[count++] = styles[i].style;
         }
@@ -1896,10 +2224,10 @@
  */
 StyleItem[] itemize () {
     segmentsText = getSegmentsText();
-    int length = segmentsText.length;
+    int length_ = segmentsText.length;
     SCRIPT_CONTROL scriptControl;
     SCRIPT_STATE scriptState;
-    final int MAX_ITEM = length + 1;
+    final int MAX_ITEM = length_ + 1;
 
     if ((orientation & DWT.RIGHT_TO_LEFT) !is 0) {
         scriptState.uBidiLevel = 1;
@@ -1926,23 +2254,28 @@
  *  Merge styles ranges and script items
  */
 StyleItem[] merge (SCRIPT_ITEM* items, int itemCount) {
+    if (styles.length > stylesCount) {
+        StyleItem[] newStyles = new StyleItem[stylesCount];
+        System.arraycopy(styles, 0, newStyles, 0, stylesCount);
+        styles = newStyles;
+    }
     int count = 0, start = 0, end = segmentsText.length, itemIndex = 0, styleIndex = 0;
-    StyleItem[] runs = new StyleItem[itemCount + styles.length];
-    SCRIPT_ITEM* scriptItem;
+    StyleItem[] runs = new StyleItem[itemCount + stylesCount];
+    SCRIPT_ITEM* scriptItem = new SCRIPT_ITEM();
     bool linkBefore = false;
     while (start < end) {
         StyleItem item = new StyleItem();
         item.start = start;
         item.style = styles[styleIndex].style;
         runs[count++] = item;
-        scriptItem = items + itemIndex;
+        *scriptItem = items[itemIndex];
         item.analysis = scriptItem.a;
         if (linkBefore) {
             item.analysis.fLinkBefore = true;
             linkBefore = false;
         }
         //scriptItem.a = new SCRIPT_ANALYSIS();
-        scriptItem = items + (itemIndex + 1);
+        *scriptItem = items[ itemIndex + 1];
         int itemLimit = scriptItem.iCharPos;
         int styleLimit = translateOffset(styles[styleIndex + 1].start);
         if (styleLimit <= itemLimit) {
@@ -1951,7 +2284,7 @@
             if (start < itemLimit && 0 < start && start < end) {
                 char pChar = segmentsText.charAt(start - 1);
                 char tChar = segmentsText.charAt(start);
-                if (!Compatibility.isWhitespace(pChar) && !Compatibility.isWhitespace(tChar)) {
+                if (Compatibility.isLetter(pChar) && Compatibility.isLetter(tChar)) {
                     item.analysis.fLinkAfter = true;
                     linkBefore = true;
                 }
@@ -1965,7 +2298,7 @@
     }
     StyleItem item = new StyleItem();
     item.start = end;
-    scriptItem = items + itemCount;
+    *scriptItem = items[ itemCount ];
     item.analysis = scriptItem.a;
     runs[count++] = item;
     if (runs.length !is count) {
@@ -2114,10 +2447,11 @@
 public void setFont (Font font) {
     checkLayout();
     if (font !is null && font.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
-    if (this.font is font) return;
-    if (font !is null && font ==/*eq*/ this.font) return;
+    Font oldFont = this.font;
+    if (oldFont is font) return;
+    this.font = font;
+    if (oldFont !is null && oldFont.opEquals(font)) return;
     freeRuns();
-    this.font = font;
 }
 
 /**
@@ -2256,7 +2590,7 @@
     start = Math.min(Math.max(0, start), length_ - 1);
     end = Math.min(Math.max(0, end), length_ - 1);
     int low = -1;
-    int high = styles.length;
+    int high = stylesCount;
     while (high - low > 1) {
         int index = (high + low) / 2;
         if (styles[index + 1].start > start) {
@@ -2265,7 +2599,7 @@
             low = index;
         }
     }
-    if (0 <= high && high < styles.length) {
+    if (0 <= high && high < stylesCount) {
         StyleItem item = styles[high];
         if (item.start is start && styles[high + 1].start - 1 is end) {
             if (style is null) {
@@ -2278,7 +2612,7 @@
     freeRuns();
     int modifyStart = high;
     int modifyEnd = modifyStart;
-    while (modifyEnd < styles.length) {
+    while (modifyEnd < stylesCount) {
         if (styles[modifyEnd + 1].start > end) break;
         modifyEnd++;
     }
@@ -2290,33 +2624,42 @@
             return;
         }
         if (styleStart !is start && styleEnd !is end) {
-            StyleItem[] newStyles = new StyleItem[styles.length + 2];
-            System.arraycopy(styles, 0, newStyles, 0, modifyStart + 1);
+            int newLength = stylesCount + 2;
+            if (newLength > styles.length) {
+                int newSize = Math.min(newLength + 1024, Math.max(64, newLength * 2));
+                StyleItem[] newStyles = new StyleItem[newSize];
+                System.arraycopy(styles, 0, newStyles, 0, stylesCount);
+                styles = newStyles;
+            }
+            System.arraycopy(styles, modifyEnd + 1, styles, modifyEnd + 3, stylesCount - modifyEnd - 1);
             StyleItem item = new StyleItem();
             item.start = start;
             item.style = style;
-            newStyles[modifyStart + 1] = item;
+            styles[modifyStart + 1] = item;
             item = new StyleItem();
             item.start = end + 1;
             item.style = styles[modifyStart].style;
-            newStyles[modifyStart + 2] = item;
-            System.arraycopy(styles, modifyEnd + 1, newStyles, modifyEnd + 3, styles.length - modifyEnd - 1);
-            styles = newStyles;
+            styles[modifyStart + 2] = item;
+            stylesCount = newLength;
             return;
         }
     }
     if (start is styles[modifyStart].start) modifyStart--;
     if (end is styles[modifyEnd + 1].start - 1) modifyEnd++;
-    int newLength = styles.length + 1 - (modifyEnd - modifyStart - 1);
-    StyleItem[] newStyles = new StyleItem[newLength];
-    System.arraycopy(styles, 0, newStyles, 0, modifyStart + 1);
+    int newLength = stylesCount + 1 - (modifyEnd - modifyStart - 1);
+    if (newLength > styles.length) {
+        int newSize = Math.min(newLength + 1024, Math.max(64, newLength * 2));
+        StyleItem[] newStyles = new StyleItem[newSize];
+        System.arraycopy(styles, 0, newStyles, 0, stylesCount);
+        styles = newStyles;
+    }
+    System.arraycopy(styles, modifyEnd, styles, modifyStart + 2, stylesCount - modifyEnd);
     StyleItem item = new StyleItem();
     item.start = start;
     item.style = style;
-    newStyles[modifyStart + 1] = item;
-    styles[modifyEnd].start = end + 1;
-    System.arraycopy(styles, modifyEnd, newStyles, modifyStart + 2, styles.length - modifyEnd);
-    styles = newStyles;
+    styles[modifyStart + 1] = item;
+    styles[modifyStart + 2].start = end + 1;
+    stylesCount = newLength;
 }
 
 /**
@@ -2369,6 +2712,7 @@
     styles[0] = new StyleItem();
     styles[1] = new StyleItem();
     styles[1].start = text.length;
+    stylesCount = 2;
 }
 
 /**
@@ -2419,12 +2763,21 @@
     return false;
 }
 
+struct CallbackDataEnumFontFamExProc {
+    int delegate ( ENUMLOGFONTEX* lpelfe, NEWTEXTMETRICEX* lpntme, int FontType, int lParam) EnumFontFamExProc;
+    int lParam;
+}
+extern(Windows) private static int EnumFontFamExProcFunc( ENUMLOGFONTEX* lpelfe, NEWTEXTMETRICEX* lpntme, int FontType, int lParam) {
+    auto cb = cast(CallbackDataEnumFontFamExProc*)cast(void*)lParam;
+    return cb.EnumFontFamExProc( lpelfe, lpntme, FontType, cb.lParam );
+}
+
 /*
  * Generate glyphs for one Run.
  */
 void shape (HDC hdc, StyleItem run) {
-    int[] buffer = new int[1];
-    char[] chars = new char[run.length];
+    final int[] buffer = new int[1];
+    final char[] chars = new char[run.length];
     segmentsText.getChars(run.start, run.start + run.length, chars, 0);
     wchar[] wchars = StrToWCHARs( chars );
     int maxGlyphs = (chars.length * 3 / 2) + 16;
@@ -2435,9 +2788,29 @@
     if (run.clusters is null) DWT.error(DWT.ERROR_NO_HANDLES);
     run.visAttrs = cast(SCRIPT_VISATTR*)OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, maxGlyphs * SCRIPT_VISATTR_SIZEOF);
     if (run.visAttrs is null) DWT.error(DWT.ERROR_NO_HANDLES);
-    run.psc = cast(SCRIPT_CACHE*)OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, 4);
+    run.psc = cast(SCRIPT_CACHE*)OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, (void*).sizeof);
     if (run.psc is null) DWT.error(DWT.ERROR_NO_HANDLES);
-    if (!shape(hdc, run, chars, buffer,  maxGlyphs)) {
+    bool shapeSucceed = shape(hdc, run, chars, buffer,  maxGlyphs);
+    final short script = run.analysis.eScript;
+
+    if (!shapeSucceed) {
+        /*
+         * Shape failed.
+         * Try to shape with fNoGlyphIndex when the run is in the
+         * Private Use Area. This allows for end-user-defined character (EUDC).
+         */
+        auto properties = device.scripts[script];
+        if (properties.fPrivateUseArea) {
+            run.analysis.fNoGlyphIndex = true;
+            shapeSucceed = shape(hdc, run, chars, buffer,  maxGlyphs);
+        }
+    }
+
+    if (!shapeSucceed) {
+        /*
+        * Shape Failed.
+        * Try to use MLANG to find a suitable font to shape the run.
+        */
         if (mLangFontLink2 !is null) {
             int dwCodePages;
             int cchCodePages;
@@ -2447,52 +2820,152 @@
             /* MapFont() */
             if (OS.VtblCall(10, mLangFontLink2, cast(int)hdc, dwCodePages, cast(int)wchars[0], cast(int)hNewFont) is OS.S_OK) {
                 auto hFont = OS.SelectObject(hdc, hNewFont);
-                if (shape(hdc, run, chars, buffer, maxGlyphs)) {
+                shapeSucceed = shape(hdc, run, chars, buffer,  maxGlyphs);
+                if (shapeSucceed) {
                     run.fallbackFont = hNewFont;
                 } else {
                     /* ReleaseFont() */
                     OS.VtblCall(8, mLangFontLink2, cast(int)hNewFont);
                     OS.SelectObject(hdc, hFont);
-                    SCRIPT_PROPERTIES* properties;
-                    properties = device.scripts[run.analysis.eScript];
-                    if (properties.fPrivateUseArea) {
-                        run.analysis.fNoGlyphIndex = true;
-                    }
-                    OS.ScriptShape(hdc, run.psc, wchars.ptr, wchars.length, maxGlyphs, &run.analysis, run.glyphs, run.clusters, run.visAttrs, buffer.ptr);
-                    run.glyphCount = buffer[0];
                 }
             }
         }
     }
-    ABC abc;
+
+    if (!shapeSucceed) {
+        /*
+        * Shape Failed.
+        * Try to shape the run using the LOGFONT in the cache.
+        */
+        auto hFont = OS.GetCurrentObject(hdc, OS.OBJ_FONT);
+        LOGFONT logFont;
+        OS.GetObject(hFont, LOGFONT.sizeof, &logFont);
+
+        LOGFONT* cachedLogFont = device.logFontsCache !is null ? device.logFontsCache[script] : null;
+        if (cachedLogFont !is null) {
+            cachedLogFont.lfHeight = logFont.lfHeight;
+            cachedLogFont.lfWeight = logFont.lfWeight;
+            cachedLogFont.lfItalic = logFont.lfItalic;
+            cachedLogFont.lfWidth = logFont.lfWidth;
+            auto newFont = OS.CreateFontIndirect(cachedLogFont);
+            OS.SelectObject(hdc, newFont);
+            shapeSucceed = shape(hdc, run, chars, buffer,  maxGlyphs);
+            if (shapeSucceed) {
+                run.fallbackFont = newFont;
+            } else {
+                OS.SelectObject(hdc, hFont);
+                OS.DeleteObject(newFont);
+            }
+        }
+        if (!shapeSucceed) {
+            /*
+            * Shape Failed.
+            * Use EnumFontFamExProc to iterate over every font in the system that supports
+            * the charset of the run and try to shape it.
+            */
+            if (device.logFontsCache is null) device.logFontsCache = new LOGFONT*[device.scripts.length];
+            LOGFONT newLogFont;
+
+            int EnumFontFamExProc( ENUMLOGFONTEX* lpelfe, NEWTEXTMETRICEX* lpntme, int FontType, int lParam) {
+                OS.MoveMemory(&newLogFont, cast(void*)lpelfe, LOGFONT.sizeof);
+                if (FontType is OS.RASTER_FONTTYPE) return 1;
+                newLogFont.lfHeight = logFont.lfHeight;
+                newLogFont.lfWeight = logFont.lfWeight;
+                newLogFont.lfItalic = logFont.lfItalic;
+                newLogFont.lfWidth = logFont.lfWidth;
+                auto newFont = OS.CreateFontIndirect(&newLogFont);
+                OS.SelectObject(hdc, newFont);
+                if (shape(hdc, run, chars, buffer, maxGlyphs)) {
+                    run.fallbackFont = newFont;
+                    LOGFONT* cacheLogFont = new LOGFONT();
+                    OS.MoveMemory(cacheLogFont, lpelfe, LOGFONT.sizeof);
+                    device.logFontsCache[script] = cacheLogFont;
+                    return 0;
+                }
+                OS.SelectObject(hdc, hFont);
+                OS.DeleteObject(newFont);
+                return 1;
+            }
+            CallbackDataEnumFontFamExProc cb;
+            cb.EnumFontFamExProc = &EnumFontFamExProc;
+            cb.lParam = 0;
+            auto properties = device.scripts[script];
+            int charSet = properties.fAmbiguousCharSet ? OS.DEFAULT_CHARSET : properties.bCharSet;
+            newLogFont.lfCharSet = cast(byte)charSet;
+            OS.EnumFontFamiliesEx(hdc, &newLogFont, &EnumFontFamExProcFunc, cast(int) &cb, 0);
+            shapeSucceed = run.fallbackFont !is null;
+        }
+    }
+
+    if (!shapeSucceed) {
+        /*
+        * Shape Failed.
+        * Give up and shape the run with the default font.
+        * Missing glyphs typically will be represent as black boxes in the text.
+        */
+        auto wchars_ = StrToWCHARs(chars);
+        OS.ScriptShape(hdc, run.psc, wchars_.ptr, wchars_.length, maxGlyphs, &run.analysis, run.glyphs, run.clusters, run.visAttrs, buffer.ptr);
+        run.glyphCount = buffer[0];
+    }
+    int[3] abc;
     run.advances = cast(int*)OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, run.glyphCount * 4);
     if (run.advances is null) DWT.error(DWT.ERROR_NO_HANDLES);
     run.goffsets = cast(GOFFSET*)OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, run.glyphCount * GOFFSET_SIZEOF);
     if (run.goffsets is null) DWT.error(DWT.ERROR_NO_HANDLES);
-    OS.ScriptPlace(hdc, run.psc, run.glyphs, run.glyphCount, run.visAttrs, &run.analysis, run.advances, run.goffsets, &abc);
-    if (run.style !is null && run.style.metrics !is null) {
-        GlyphMetrics metrics = run.style.metrics;
-        /*
-        *  Bug in Windows, on a Japanese machine, Uniscribe returns glyphcount
-        *  equals zero for FFFC (possibly other unicode code points), the fix
-        *  is to make sure the glyph is at least one pixel wide.
-        */
-        run.width = metrics.width * Math.max (1, run.glyphCount);
-        run.ascent = metrics.ascent;
-        run.descent = metrics.descent;
-        run.leading = 0;
+    OS.ScriptPlace(hdc, run.psc, run.glyphs, run.glyphCount, run.visAttrs, &run.analysis, run.advances, run.goffsets, cast(ABC*)abc.ptr);
+    run.width = abc[0] + abc[1] + abc[2];
+    TextStyle style = run.style;
+    if (style !is null) {
+        OUTLINETEXTMETRIC* lotm = null;
+        if (style.underline || style.strikeout) {
+            lotm = new OUTLINETEXTMETRIC();
+            if (OS.GetOutlineTextMetrics(hdc, OUTLINETEXTMETRIC.sizeof, lotm) is 0) {
+                lotm = null;
+            }
+        }
+        if (style.metrics !is null) {
+            GlyphMetrics metrics = style.metrics;
+            /*
+             *  Bug in Windows, on a Japanese machine, Uniscribe returns glyphcount
+             *  equals zero for FFFC (possibly other unicode code points), the fix
+             *  is to make sure the glyph is at least one pixel wide.
+             */
+            run.width = metrics.width * Math.max (1, run.glyphCount);
+            run.ascent = metrics.ascent;
+            run.descent = metrics.descent;
+            run.leading = 0;
+        } else {
+            TEXTMETRIC lptm;
+            if (lotm !is null) {
+                lptm = lotm.otmTextMetrics;
+            } else {
+                lptm = TEXTMETRIC.init;
+                OS.GetTextMetrics(hdc, &lptm);
+            }
+            run.ascent = lptm.tmAscent;
+            run.descent = lptm.tmDescent;
+            run.leading = lptm.tmInternalLeading;
+        }
+        if (lotm !is null) {
+            run.underlinePos = lotm.otmsUnderscorePosition;
+            run.underlineThickness = Math.max(1, lotm.otmsUnderscoreSize);
+            run.strikeoutPos = lotm.otmsStrikeoutPosition;
+            run.strikeoutThickness = Math.max(1, lotm.otmsStrikeoutSize);
+        } else {
+            run.underlinePos = 1;
+            run.underlineThickness = 1;
+            run.strikeoutPos = run.ascent / 2;
+            run.strikeoutThickness = 1;
+        }
+        run.ascent += style.rise;
+        run.descent -= style.rise;
     } else {
-        run.width = abc.abcA + abc.abcB + abc.abcC;
         TEXTMETRIC lptm;
         OS.GetTextMetrics(hdc, &lptm);
         run.ascent = lptm.tmAscent;
         run.descent = lptm.tmDescent;
         run.leading = lptm.tmInternalLeading;
     }
-    if (run.style !is null) {
-        run.ascent += run.style.rise;
-        run.descent -= +run.style.rise;
-    }
 }
 
 int validadeOffset(int offset, int step) {
--- a/dwt/graphics/TextStyle.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/graphics/TextStyle.d	Sat May 17 17:34:28 2008 +0200
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2006 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -59,13 +59,40 @@
     public Color background;
 
     /**
-     * the underline flag of the style
+     * the underline flag of the style. The default underline
+     * style is <code>DWT.UNDERLINE_SINGLE</code>.
+     *
      *
      * @since 3.1
      */
     public bool underline;
 
     /**
+     * the underline color of the style
+     *
+     * @since 3.4
+     */
+    public Color underlineColor;
+
+    /**
+     * the underline style. This style is ignored when
+     * <code>underline</code> is false.
+     * <p>
+     * This value should be one of <code>DWT.UNDERLINE_SINGLE</code>,
+     * <code>DWT.UNDERLINE_DOUBLE</code>, <code>DWT.UNDERLINE_ERROR</code>,
+     * or <code>DWT.UNDERLINE_SQUIGGLE</code>.
+     * </p>
+     *
+     * @see DWT#UNDERLINE_SINGLE
+     * @see DWT#UNDERLINE_DOUBLE
+     * @see DWT#UNDERLINE_ERROR
+     * @see DWT#UNDERLINE_SQUIGGLE
+     *
+     * @since 3.4
+     */
+    public int underlineStyle;
+
+    /**
      * the strikeout flag of the style
      *
      * @since 3.1
@@ -73,6 +100,37 @@
     public bool strikeout;
 
     /**
+     * the strikeout color of the style
+     *
+     * @since 3.4
+     */
+    public Color strikeoutColor;
+
+    /**
+     * the border style. The default border style is <code>DWT.NONE</code>.
+     * <p>
+     * This value should be one of <code>DWT.BORDER_SOLID</code>,
+     * <code>DWT.BORDER_DASH</code>,<code>DWT.BORDER_DOT</code> or
+     * <code>DWT.NONE</code>.
+     * </p>
+     *
+     * @see DWT#BORDER_SOLID
+     * @see DWT#BORDER_DASH
+     * @see DWT#BORDER_DOT
+     * @see DWT#NONE
+     *
+     * @since 3.4
+     */
+    public int borderStyle;
+
+    /**
+     * the border color of the style
+     *
+     * @since 3.4
+     */
+    public Color borderColor;
+
+    /**
      * the GlyphMetrics of the style
      *
      * @since 3.2
@@ -86,17 +144,12 @@
      */
     public int rise;
 
-/++
- + DWT extension for clone implementation
- +/
-protected this( TextStyle other ){
-    font = other.font;
-    foreground = other.foreground;
-    background = other.background;
-    underline = other.underline;
-    strikeout = other.strikeout;
-    metrics = other.metrics;
-    rise = other.rise;
+/**
+ * Create an empty text style.
+ *
+ * @since 3.4
+ */
+public this () {
 }
 
 /**
@@ -116,6 +169,30 @@
     this.background = background;
 }
 
+
+/**
+ * Create a new text style from an existing text style.
+ *
+ *@param style the style to copy
+ *
+ * @since 3.4
+ */
+public this (TextStyle style) {
+    if (style is null) DWT.error (DWT.ERROR_INVALID_ARGUMENT);
+    font = style.font;
+    foreground = style.foreground;
+    background = style.background;
+    underline = style.underline;
+    underlineColor = style.underlineColor;
+    underlineStyle = style.underlineStyle;
+    strikeout = style.strikeout;
+    strikeoutColor = style.strikeoutColor;
+    borderStyle = style.borderStyle;
+    borderColor = style.borderColor;
+    metrics = style.metrics;
+    rise = style.rise;
+}
+
 /**
  * Compares the argument to the receiver, and returns true
  * if they represent the <em>same</em> object using a class
@@ -142,8 +219,20 @@
     } else if (style.font !is null) return false;
     if (metrics !is null || style.metrics !is null) return false;
     if (underline !is style.underline) return false;
+    if (underlineStyle !is style.underlineStyle) return false;
+    if (borderStyle !is style.borderStyle) return false;
     if (strikeout !is style.strikeout) return false;
     if (rise !is style.rise) return false;
+    if (underlineColor !is null) {
+        if (!underlineColor.equals(style.underlineColor)) return false;
+    } else if (style.underlineColor !is null) return false;
+    if (strikeoutColor !is null) {
+        if (!strikeoutColor.equals(style.strikeoutColor)) return false;
+    } else if (style.strikeoutColor !is null) return false;
+    if (underlineStyle !is style.underlineStyle) return false;
+    if (borderColor !is null) {
+        if (!borderColor.equals(style.borderColor)) return false;
+    } else if (style.borderColor !is null) return false;
     return true;
 }
 
@@ -166,9 +255,44 @@
     if (underline) hash ^= hash;
     if (strikeout) hash ^= hash;
     hash ^= rise;
+    if (underlineColor !is null) hash ^= underlineColor.hashCode();
+    if (strikeoutColor !is null) hash ^= strikeoutColor.hashCode();
+    if (borderColor !is null) hash ^= borderColor.hashCode();
+    hash ^= underlineStyle;
     return hash;
 }
 
+bool isAdherentBorder(TextStyle style) {
+    if (this is style) return true;
+    if (style is null) return false;
+    if (borderStyle !is style.borderStyle) return false;
+    if (borderColor !is null) {
+        if (!borderColor.equals(style.borderColor)) return false;
+    } else if (style.borderColor !is null) return false;
+    return true;
+}
+
+bool isAdherentUnderline(TextStyle style) {
+    if (this is style) return true;
+    if (style is null) return false;
+    if (underline !is style.underline) return false;
+    if (underlineStyle !is style.underlineStyle) return false;
+    if (underlineColor !is null) {
+        if (!underlineColor.equals(style.underlineColor)) return false;
+    } else if (style.underlineColor !is null) return false;
+    return true;
+}
+
+bool isAdherentStrikeout(TextStyle style) {
+    if (this is style) return true;
+    if (style is null) return false;
+    if (strikeout !is style.strikeout) return false;
+    if (strikeoutColor !is null) {
+        if (!strikeoutColor.equals(style.strikeoutColor)) return false;
+    } else if (style.strikeoutColor !is null) return false;
+    return true;
+}
+
 /**
  * Returns a string containing a concise, human-readable
  * description of the receiver.
--- a/dwt/graphics/Transform.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/graphics/Transform.d	Sat May 17 17:34:28 2008 +0200
@@ -39,7 +39,7 @@
  * @since 3.1
  */
 public class Transform : Resource {
-
+    alias Resource.init_ init_;
     /**
      * the OS resource for the Transform
      * (Warning: This field is platform dependent)
@@ -137,13 +137,11 @@
  * @see #dispose()
  */
 public this (Device device, float m11, float m12, float m21, float m22, float dx, float dy) {
-    if (device is null) device = Device.getDevice();
-    if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
-    this.device = device;
-    device.checkGDIP();
+    super(device);
+    this.device.checkGDIP();
     handle = Gdip.Matrix_new(m11, m12, m21, m22, dx, dy);
     if (handle is null) DWT.error(DWT.ERROR_NO_HANDLES);
-    if (device.tracking) device.new_Object(this);
+    init_();
 }
 
 static float[] checkTransform(float[] elements) {
@@ -152,18 +150,9 @@
     return elements;
 }
 
-/**
- * Disposes of the operating system resources associated with
- * the Transform. Applications must dispose of all Transforms that
- * they allocate.
- */
-override public void dispose() {
-    if (handle is null) return;
-    if (device.isDisposed()) return;
+void destroy() {
     Gdip.Matrix_delete(handle);
     handle = null;
-    if (device.tracking) device.dispose_Object(this);
-    device = null;
 }
 
 /**
@@ -184,11 +173,26 @@
     if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
     if (elements is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
     if (elements.length < 6) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
-    Gdip.Matrix_GetElements(handle, elements);
+    Gdip.Matrix_GetElements(handle, elements.ptr);
 }
 
 /**
  * Modifies the receiver such that the matrix it represents becomes the
+ * identity matrix.
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.4
+ */
+public void identity() {
+    if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
+    Gdip.Matrix_SetElements(handle, 1, 0, 0, 1, 0, 0);
+}
+
+/**
+ * Modifies the receiver such that the matrix it represents becomes
  * the mathematical inverse of the matrix it previously represented.
  *
  * @exception DWTException <ul>
@@ -303,6 +307,24 @@
 }
 
 /**
+ * Modifies the receiver so that it represents a transformation that is
+ * equivalent to its previous transformation sheared by (shearX, shearY).
+ *
+ * @param shearX the shear factor in the X direction
+ * @param shearY the shear factor in the Y direction
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.4
+ */
+public void shear(float shearX, float shearY) {
+    if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
+    Gdip.Matrix_Shear(handle, shearX, shearY, Gdip.MatrixOrderPrepend);
+}
+
+/**
  * Given an array containing points described by alternating x and y values,
  * modify that array such that each point has been replaced with the result of
  * applying the transformation represented by the receiver to that point.
@@ -319,7 +341,7 @@
 public void transform(float[] pointArray) {
     if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
     if (pointArray is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
-    Gdip.Matrix_TransformPoints(handle, cast(Gdip.PointF[])pointArray, pointArray.length / 2);
+    Gdip.Matrix_TransformPoints(handle, cast(Gdip.PointF*)pointArray.ptr, pointArray.length / 2);
 }
 
 /**
--- a/dwt/internal/BidiUtil.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/BidiUtil.d	Sat May 17 17:34:28 2008 +0200
@@ -17,6 +17,7 @@
 import dwt.graphics.GC;
 import dwt.internal.win32.OS;
 
+import dwt.widgets.Control;
 import tango.util.Convert;
 import dwt.dwthelper.utils;
 import dwt.dwthelper.Runnable;
@@ -112,6 +113,9 @@
     languageMap[hwnd] = runnable;
     subclass(hwnd);
 }
+public static void addLanguageListener (Control control, Runnable runnable) {
+    addLanguageListener(control.handle, runnable);
+}
 /**
  * Proc used for OS.EnumSystemLanguageGroups call during isBidiPlatform test.
  */
@@ -407,11 +411,9 @@
  */
 public static int getKeyboardLanguage() {
     int layout = cast(int) OS.GetKeyboardLayout(0);
-    // only interested in low 2 bytes, which is the primary
-    // language identifier
-    layout = layout & 0x000000FF;
-    if (layout is LANG_HEBREW) return KEYBOARD_BIDI;
-    if (layout is LANG_ARABIC) return KEYBOARD_BIDI;
+    int langID = OS.PRIMARYLANGID(OS.LOWORD(layout));
+    if (langID is LANG_HEBREW) return KEYBOARD_BIDI;
+    if (langID is LANG_ARABIC) return KEYBOARD_BIDI;
     // return non-bidi for all other languages
     return KEYBOARD_NON_BIDI;
 }
@@ -482,7 +484,7 @@
 public static bool isKeyboardBidi() {
     void*[] list = getKeyboardLanguageList();
     for (int i=0; i<list.length; i++) {
-        int id = cast(int)list[i] & 0x000000FF;
+        int id = OS.PRIMARYLANGID(OS.LOWORD( cast(int) list[i]));
         if ((id is LANG_ARABIC) || (id is LANG_HEBREW)) {
             return true;
         }
@@ -499,6 +501,9 @@
     languageMap.remove(hwnd);
     unsubclass(hwnd);
 }
+public static void removeLanguageListener (Control control) {
+    removeLanguageListener(control.handle);
+}
 /**
  * Switch the keyboard language to the specified language type.  We do
  * not distinguish between multiple bidi or multiple non-bidi languages, so
@@ -517,7 +522,7 @@
         void*[] list = getKeyboardLanguageList();
         // set to first bidi language
         for (int i=0; i<list.length; i++) {
-            int id = cast(int)list[i] & 0x000000FF;
+            int id = OS.PRIMARYLANGID(OS.LOWORD( cast(int) list[i]));
             if ((id is LANG_ARABIC) || (id is LANG_HEBREW)) {
                 OS.ActivateKeyboardLayout(list[i], 0);
                 return;
@@ -529,7 +534,7 @@
         // set to the first non-bidi language (anything not
         // Hebrew or Arabic)
         for (int i=0; i<list.length; i++) {
-            int id = cast(int)list[i] & 0x000000FF;
+            int id = OS.PRIMARYLANGID(OS.LOWORD( cast(int) list[i]));
             if ((id !is LANG_HEBREW) && (id !is LANG_ARABIC)) {
                 OS.ActivateKeyboardLayout(list[i], 0);
                 return;
@@ -559,6 +564,9 @@
     OS.SetWindowLong (hwnd, OS.GWL_EXSTYLE, bits);
     return true;
 }
+public static bool setOrientation (Control control, int orientation) {
+    return setOrientation(control.handle, orientation);
+}
 /**
  * Override the window proc.
  *
@@ -567,10 +575,10 @@
 static void subclass(HWND hwnd) {
     HWND key = hwnd;
     if ( ( key in oldProcMap ) is null) {
-        int oldProc = OS.GetWindowLong(hwnd, OS.GWL_WNDPROC);
+        int /*long*/ oldProc = OS.GetWindowLongPtr(hwnd, OS.GWLP_WNDPROC);
         oldProcMap[key] = cast(WNDPROC)oldProc;
         WNDPROC t = &windowProc; // test signature
-        OS.SetWindowLong(hwnd, OS.GWL_WNDPROC, cast(int) &windowProc);
+        OS.SetWindowLongPtr(hwnd, OS.GWLP_WNDPROC, cast(LONG_PTR)&windowProc);
     }
 }
 /**
@@ -634,7 +642,7 @@
             oldProcMap.remove( key );
         }
         if (proc is null) return;
-        OS.SetWindowLong(hwnd, OS.GWL_WNDPROC, cast(int)proc );
+        OS.SetWindowLongPtr(hwnd, OS.GWLP_WNDPROC, cast(LONG_PTR) proc );
     }
 }
 /**
@@ -656,7 +664,7 @@
         default:
         }
     auto oldProc = oldProcMap[key];
-    return OS.CallWindowProc ( oldProc, hwnd, msg, wParam, lParam);
+    return oldProc( hwnd, msg, wParam, lParam);
 }
 
 }
--- a/dwt/internal/Compatibility.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/Compatibility.d	Sat May 17 17:34:28 2008 +0200
@@ -14,9 +14,11 @@
 
 /+
 import java.io.*;
+import java.io.File;
 import java.text.MessageFormat;
 import java.util.MissingResourceException;
 import java.util.ResourceBundle;
+import java.util.zip.DeflaterOutputStream;
 import java.util.zip.InflaterInputStream;
 +/
 
@@ -29,6 +31,7 @@
 import Unicode = tango.text.Unicode;
 import tango.sys.Process;
 import dwt.dwthelper.utils;
+import tango.io.Path;
 
 /**
  * This class is a placeholder for utility methods commonly
@@ -109,6 +112,17 @@
 }
 
 /**
+ * Answers whether the indicated file exists or not.
+ *
+ * @param parent the file's parent directory
+ * @param child the file's name
+ * @return true if the file exists
+ */
+public static bool fileExists(String parent, String child) {
+    return FS.exists( FS.join(parent, child));
+}
+
+/**
  * Answers the most positive (i.e. closest to positive infinity)
  * integer value which is less than the number obtained by dividing
  * the first argument p by the second argument q.
@@ -158,6 +172,22 @@
 }
 
 /**
+ * Create an DeflaterOutputStream if such things are supported.
+ *
+ * @param stream the output stream
+ * @return a deflater stream or <code>null</code>
+ * @exception IOException
+ *
+ * @since 3.4
+ */
+public static OutputStream newDeflaterOutputStream(OutputStream stream) {
+    //DWT_TODO
+    implMissing(__FILE__,__LINE__);
+    return null;
+    //return new DeflaterOutputStream(stream);
+}
+
+/**
  * Open a file if such things are supported.
  *
  * @param filename the name of the file to open
--- a/dwt/internal/ImageList.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/ImageList.d	Sat May 17 17:34:28 2008 +0200
@@ -138,8 +138,8 @@
             bmi[offset + 10] = cast(byte)((blueMask & 0xFF00) >> 8);
             bmi[offset + 11] = cast(byte)((blueMask & 0xFF) >> 0);
         }
-        int[1] pBits;
-        hBitmap = OS.CreateDIBSection(null, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS, pBits.ptr, null, 0);
+        void* pBits;
+        hBitmap = OS.CreateDIBSection(null, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS, &pBits, null, 0);
     } else {
         hBitmap = OS.CreateCompatibleBitmap (hDC, width, height);
     }
@@ -183,8 +183,8 @@
     byte [] bmi = new byte[BITMAPINFOHEADER.sizeof];
     *cast(BITMAPINFOHEADER*)bmi.ptr = bmiHeader;
     //OS.MoveMemory (bmi, bmiHeader, BITMAPINFOHEADER.sizeof);
-    int [1] pBits;
-    auto memDib = OS.CreateDIBSection (null, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS, pBits.ptr, null, 0);
+    void* pBits;
+    auto memDib = OS.CreateDIBSection (null, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS, &pBits, null, 0);
     if (memDib is null) DWT.error (DWT.ERROR_NO_HANDLES);
     auto oldMemBitmap = OS.SelectObject (memHdc, memDib);
 
@@ -237,8 +237,8 @@
         byte [] bmi2 = new byte[BITMAPINFOHEADER.sizeof];
         *cast(BITMAPINFOHEADER*)bmi2.ptr = bmiHeader2;
         //OS.MoveMemory (bmi2, bmiHeader2, BITMAPINFOHEADER.sizeof);
-        int [1] pBits2;
-        auto memDib2 = OS.CreateDIBSection (null, cast(BITMAPINFO*)bmi2.ptr, OS.DIB_RGB_COLORS, pBits2.ptr, null, 0);
+        void* pBits2;
+        auto memDib2 = OS.CreateDIBSection (null, cast(BITMAPINFO*)bmi2.ptr, OS.DIB_RGB_COLORS, &pBits2, null, 0);
         auto memHdc2 = OS.CreateCompatibleDC (hdc);
         auto oldMemBitmap2 = OS.SelectObject (memHdc2, memDib2);
         static if (!OS.IsWinCE) OS.SetStretchBltMode(memHdc2, OS.COLORONCOLOR);
--- a/dwt/internal/Library.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/Library.d	Sat May 17 17:34:28 2008 +0200
@@ -34,7 +34,7 @@
     /**
      * DWT Minor version number (must be in the range 0..999)
      */
-    static const int MINOR_VERSION = 349;
+    static const int MINOR_VERSION = 442;
 
     /**
      * DWT revision number (must be >= 0)
@@ -178,6 +178,20 @@
  * @param mapName true if the name should be mapped, false otherwise
  */
 public static void loadLibrary (String name, boolean mapName) {
+    String prop = System.getProperty ("sun.arch.data.model"); //$NON-NLS-1$
+    if (prop is null) prop = System.getProperty ("com.ibm.vm.bitmode"); //$NON-NLS-1$
+    if (prop !is null) {
+        if ("32".equals (prop)) { //$NON-NLS-1$
+             if (0x1FFFFFFFFL is (int /*long*/)0x1FFFFFFFFL) {
+                throw new UnsatisfiedLinkError ("Cannot load 64-bit DWT libraries on 32-bit JVM"); //$NON-NLS-1$
+             }
+        }
+        if ("64".equals (prop)) { //$NON-NLS-1$
+            if (0x1FFFFFFFFL !is (int /*long*/)0x1FFFFFFFFL) {
+                throw new UnsatisfiedLinkError ("Cannot load 32-bit DWT libraries on 64-bit JVM"); //$NON-NLS-1$
+            }       
+        }
+    }
 
     /* Compute the library name and mapped name */
     String libName1, libName2, mappedName1, mappedName2;
--- a/dwt/internal/gdip/Gdip.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/gdip/Gdip.d	Sat May 17 17:34:28 2008 +0200
@@ -791,13 +791,13 @@
 	**************************************************************************/
 
 	static Status LinearGradientBrush_SetInterpolationColors( LinearGradientBrush brush,
-							  ARGB[] presetColors, float[] blendPositions, int count )
+							  ARGB* presetColors, float* blendPositions, int count )
 	{
 		if ((count <= 0) || presetColors is null)
             return SetStatus(Status.InvalidParameter);
 
-		return SetStatus(GdipSetLinePresetBlend(brush, presetColors.ptr,
-													   blendPositions.ptr,
+		return SetStatus(GdipSetLinePresetBlend(brush, presetColors,
+													   blendPositions,
 													   count ) );
 	}
 
@@ -1004,9 +1004,9 @@
 
 	**************************************************************************/
 
-	static Status Pen_SetDashPattern( Pen pen, float[] dashArray, int count )
+	static Status Pen_SetDashPattern( Pen pen, float* dashArray, int count )
 	{
-		return SetStatus(GdipSetPenDashArray(pen, dashArray.ptr, count));
+		return SetStatus(GdipSetPenDashArray(pen, dashArray, count));
 	}
 
 	/**************************************************************************
@@ -1276,11 +1276,11 @@
 
 	**************************************************************************/
 
-	static Path GraphicsPath_new( Point[] points, ubyte[] types, int count,
+	static Path GraphicsPath_new( Point* points, ubyte* types, int count,
 								  FillMode fillMode = FillModeAlternate )
 	{
         Path path = null;
-        lastResult = GdipCreatePath2I(points.ptr, types.ptr, count, fillMode, path);
+        lastResult = GdipCreatePath2I(points, types, count, fillMode, path);
 		return path;
 	}
 
@@ -1292,6 +1292,11 @@
 	{
 		GdipDeletePath(path);
 	}
+    static Path GraphicsPath_Clone( Handle path ){
+        Path clonepath = null;
+        SetStatus( GdipClonePath(path, clonepath));
+        return clonepath;
+    }
 
 
 	static Status GraphicsPath_AddArcF( Path path, float x,     float y,
@@ -1427,18 +1432,18 @@
 
 	**************************************************************************/
 
-	static Status GraphicsPath_GetPathTypes( Path path, byte[] types, int count )
+	static Status GraphicsPath_GetPathTypes( Path path, byte* types, int count )
 	{
-		return SetStatus( GdipGetPathTypes( path, types.ptr, count) );
+		return SetStatus( GdipGetPathTypes( path, types, count) );
 	}
 
 	/**************************************************************************
 
 	**************************************************************************/
 
-	static Status GraphicsPath_GetPathPoints( Path path, PointF[] points, int count)
+	static Status GraphicsPath_GetPathPoints( Path path, PointF* points, int count)
     {
-        return SetStatus(GdipGetPathPoints(path, points.ptr, count));
+        return SetStatus(GdipGetPathPoints(path, points, count));
     }
 
 
@@ -1605,9 +1610,9 @@
 
 	**************************************************************************/
 
-	static Status Graphics_DrawLines( Graphics graphics, Pen pen, Point[] points, uint count )
+	static Status Graphics_DrawLines( Graphics graphics, Pen pen, Point* points, uint count )
 	{
-		return SetStatus(GdipDrawLinesI(graphics, pen, points.ptr, count));
+		return SetStatus(GdipDrawLinesI(graphics, pen, points, count));
 	}
 
 	/**************************************************************************
@@ -1623,9 +1628,9 @@
 
 	**************************************************************************/
 
-	static Status Graphics_DrawPolygon(Graphics graphics, Pen pen, Point[] points, uint count )
+	static Status Graphics_DrawPolygon(Graphics graphics, Pen pen, Point* points, uint count )
 	{
-		return SetStatus(GdipDrawPolygonI(graphics, pen, points.ptr, count));
+		return SetStatus(GdipDrawPolygonI(graphics, pen, points, count));
 
 	}
 
@@ -1712,9 +1717,9 @@
 	**************************************************************************/
 
 	static Status Graphics_FillPolygon( Graphics graphics, Brush brush,
-										Point[] points, int count, FillMode fillMode )
+										Point* points, int count, FillMode fillMode )
 	{
-		return SetStatus(GdipFillPolygonI(graphics, brush, points.ptr, count, fillMode));
+		return SetStatus(GdipFillPolygonI(graphics, brush, points, count, fillMode));
 	}
 
 	/**************************************************************************
@@ -1938,7 +1943,7 @@
 
 	**************************************************************************/
 
-	static Status Graphics_SetClip( Graphics graphics, Path path,
+	static Status Graphics_SetClipPath( Graphics graphics, Path path,
 								    CombineMode combineMode = CombineModeReplace )
 	{
 		return SetStatus(GdipSetClipPath(graphics, path, combineMode));
@@ -1957,6 +1962,9 @@
                                                       combineMode));
 	}
 
+    //static Status Graphics_SetClipPath(Graphics graphics, GraphicsPath path ){
+    //    return SetStatus( SetClipPath( graphics, path ));
+    //}
 	/**************************************************************************
 
 	**************************************************************************/
@@ -2125,9 +2133,9 @@
 
 	**************************************************************************/
 
-    static Status Matrix_GetElements( Matrix matrix, float[] m )
+    static Status Matrix_GetElements( Matrix matrix, float* m )
 	{
-		return SetStatus( GdipGetMatrixElements( matrix, m.ptr ) );
+		return SetStatus( GdipGetMatrixElements( matrix, m ) );
 	}
 
 	/**************************************************************************
@@ -2180,6 +2188,9 @@
 	{
 		return SetStatus( GdipScaleMatrix(matrix, scaleX, scaleY, order) );
 	}
+    static Status Matrix_Shear( Matrix matrix, float shearX, float shearY, MatrixOrder order ){
+        return SetStatus( GdipShearMatrix(matrix, shearX, shearY, order));
+    }
 
 	/**************************************************************************
 
@@ -2196,9 +2207,9 @@
 
 	**************************************************************************/
 
-    static Status Matrix_TransformPoints( Matrix matrix, PointF[] pts, int count = 1 )
+    static Status Matrix_TransformPoints( Matrix matrix, PointF* pts, int count = 1 )
 	{
-		return SetStatus( GdipTransformMatrixPoints( matrix, pts.ptr, count ) );
+		return SetStatus( GdipTransformMatrixPoints( matrix, pts, count ) );
 	}
 
 	/**************************************************************************
@@ -2310,10 +2321,10 @@
 	**************************************************************************/
 
 	static int StringFormat_SetTabStops( StringFormat format, float firstTabOffset,
-										 int count, float[] tabStops)
+										 int count, float* tabStops)
 	{
 		return SetStatus( GdipSetStringFormatTabStops( format, firstTabOffset,
-													   count, tabStops.ptr ) );
+													   count, tabStops ) );
 	}
 
 	/**************************************************************************
--- a/dwt/internal/image/FileFormat.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/image/FileFormat.d	Sat May 17 17:34:28 2008 +0200
@@ -12,6 +12,8 @@
  *******************************************************************************/
 module dwt.internal.image.FileFormat;
 
+import dwt.dwthelper.utils;
+
 public import dwt.graphics.ImageLoader;
 public import dwt.graphics.ImageData;
 public import dwt.internal.image.LEDataInputStream;
@@ -32,7 +34,6 @@
 
 import tango.core.Exception;
 import tango.core.Tuple;
-import dwt.dwthelper.utils;
 
 /**
  * Abstract factory class for loading/unloading images from files or streams
@@ -81,7 +82,7 @@
 public static ImageData[] load(InputStream istr, ImageLoader loader) {
     FileFormat fileFormat = null;
     LEDataInputStream stream = new LEDataInputStream(istr);
-    bool isSupported = false;
+    bool isSupported = false;   
     foreach( TFormat; TFormats ){
         try{
             fileFormat = new TFormat();
--- a/dwt/internal/image/GIFFileFormat.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/image/GIFFileFormat.d	Sat May 17 17:34:28 2008 +0200
@@ -22,9 +22,9 @@
 import dwt.graphics.ImageLoaderEvent;
 import dwt.graphics.ImageLoader;
 import tango.core.Exception;
-import dwt.dwthelper.System;
 import dwt.dwthelper.utils;
 
+
 final class GIFFileFormat : FileFormat {
     String signature;
     int screenWidth, screenHeight, backgroundPixel, bitsPerPixel, defaultDepth;
@@ -62,7 +62,7 @@
             byte[3] signature;
             stream.read(signature);
             stream.unread(signature);
-            return cast(String)signature == "GIF"; //$NON-NLS-1$
+            return signature[0] is 'G' && signature[1] is 'I' && signature[2] is 'F';
         } catch (Exception e) {
             return false;
         }
@@ -73,13 +73,12 @@
      * Return an array of ImageData representing the image(s).
      */
     override ImageData[] loadFromByteStream() {
-        byte[3] signatureBytes;
+        byte[3] signature;
         byte[3] versionBytes;
         byte[7] block;
         try {
-            inputStream.read(signatureBytes);
-            signature = cast(String)signatureBytes.dup;
-            if (signature != "GIF") //$NON-NLS-1$
+            inputStream.read(signature);
+            if (!(signature[0] is 'G' && signature[1] is 'I' && signature[2] is 'F'))
                 DWT.error(DWT.ERROR_INVALID_IMAGE);
 
             inputStream.read(versionBytes);
@@ -313,13 +312,11 @@
             // Read size of block = 0x0B.
             inputStream.read();
             // Read application identifier.
-            byte[] applicationBytes = new byte[8];
-            inputStream.read(applicationBytes);
-            String application = cast(String)(applicationBytes.dup);
+            byte[] application = new byte[8];
+            inputStream.read(application);
             // Read authentication code.
-            byte[] authenticationBytes = new byte[3];
-            inputStream.read(authenticationBytes);
-            String authentication = cast(String)(authenticationBytes.dup);
+            byte[] authentication = new byte[3];
+            inputStream.read(authentication);
             // Read application data.
             byte[] data = new byte[0];
             byte[] block = new byte[255];
@@ -333,7 +330,20 @@
                 size = inputStream.read();
             }
             // Look for the NETSCAPE 'repeat count' field for an animated GIF.
-            if (application=="NETSCAPE" && authentication=="2.0" && data[0] is 01) { //$NON-NLS-1$ //$NON-NLS-2$
+            bool netscape =
+                application[0] is 'N' &&
+                application[1] is 'E' &&
+                application[2] is 'T' &&
+                application[3] is 'S' &&
+                application[4] is 'C' &&
+                application[5] is 'A' &&
+                application[6] is 'P' &&
+                application[7] is 'E';
+            bool authentic =
+                authentication[0] is '2' &&
+                authentication[1] is '.' &&
+                authentication[2] is '0';
+            if (netscape && authentic && data[0] is 01) { //$NON-NLS-1$ //$NON-NLS-2$
                 repeatCount = (data[1] & 0xFF) | ((data[2] & 0xFF) << 8);
                 loader.repeatCount = repeatCount;
             }
--- a/dwt/internal/image/JPEGAppn.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/image/JPEGAppn.d	Sat May 17 17:34:28 2008 +0200
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
  * Copyright (c) 2000, 2003 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
@@ -26,7 +26,7 @@
         super(byteStream);
     }
 
-    override public bool verify() {
+    public override bool verify() {
         int marker = getSegmentMarker();
         return marker >= JPEGFileFormat.APP0 && marker <= JPEGFileFormat.APP15;
     }
--- a/dwt/internal/image/JPEGArithmeticConditioningTable.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/image/JPEGArithmeticConditioningTable.d	Sat May 17 17:34:28 2008 +0200
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
  * Copyright (c) 2000, 2003 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
@@ -22,7 +22,7 @@
         super(byteStream);
     }
 
-    override public int signature() {
+    public override int signature() {
         return JPEGFileFormat.DAC;
     }
 }
--- a/dwt/internal/image/JPEGComment.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/image/JPEGComment.d	Sat May 17 17:34:28 2008 +0200
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
  * Copyright (c) 2000, 2003 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
@@ -26,7 +26,7 @@
         super(byteStream);
     }
 
-    override public int signature() {
+    public override int signature() {
         return JPEGFileFormat.COM;
     }
 }
--- a/dwt/internal/image/JPEGDecoder.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/image/JPEGDecoder.d	Sat May 17 17:34:28 2008 +0200
@@ -20,12 +20,11 @@
 import dwt.graphics.ImageLoaderEvent;
 import dwt.graphics.PaletteData;
 import dwt.graphics.RGB;
+import dwt.dwthelper.utils;
 
 import tango.core.Exception;
 import tango.util.Convert;
 import Math = tango.math.Math;
-import dwt.dwthelper.System;
-import dwt.dwthelper.utils;
 
 public class JPEGDecoder {
 
@@ -980,7 +979,7 @@
                         r = s >> 4;
                         s &= 15;
                         if (s !is 0) {
-                            if (s !is 1) {       /* size of new coef should always be 1 */
+                            if (s !is 1) {      /* size of new coef should always be 1 */
 //                              WARNMS(cinfo, JWRN_HUFF_BAD_CODE);
                             }
 //                          CHECK_BIT_BUFFER(br_state, 1, goto undoit);
@@ -1243,7 +1242,7 @@
                                 k += 15;        /* skip 15 zeroes in band */
                             } else {        /* EOBr, run length is 2^r + appended bits */
                                 EOBRUN = 1 << r;
-                                if (r !is 0) {       /* EOBr, r > 0 */
+                                if (r !is 0) {      /* EOBr, r > 0 */
 //                                  CHECK_BIT_BUFFER(br_state, r, return FALSE);
                                     {
                                     if (bits_left < (r)) {
@@ -1281,7 +1280,7 @@
             return true;
         }
 
-        bool decode_mcu_DC_first (jpeg_decompress_struct cinfo, short[][] MCU_data) {
+        bool decode_mcu_DC_first (jpeg_decompress_struct cinfo, short[][] MCU_data) {    
             phuff_entropy_decoder entropy = this;
             int Al = cinfo.Al;
             int s = 0, r;
@@ -1645,7 +1644,7 @@
 
         /* Variables for Floyd-Steinberg dithering */
 //          FSERRPTR fserrors[MAX_Q_COMPS]; /* accumulated errors */
-        bool on_odd_row;
+        bool on_odd_row;    
 
         void start_pass (jpeg_decompress_struct cinfo, bool is_pre_scan) {
             error();
@@ -4449,7 +4448,7 @@
 
         length -= count;
 
-        if ((index & 0x10) !is 0) {      /* AC table definition */
+        if ((index & 0x10) !is 0) {     /* AC table definition */
             index -= 0x10;
             htblptr = cinfo.ac_huff_tbl_ptrs[index] = new JHUFF_TBL();
         } else {            /* DC table definition */
@@ -5238,7 +5237,7 @@
 //               GETJOCTET(data[12]), GETJOCTET(data[13]));
         }
         totallen -= APP0_DATA_LEN;
-        if (totallen !is ((data[12] & 0xFF) * (data[13] & 0xFF) * 3)) {
+        if (totallen !is    ((data[12] & 0xFF) * (data[13] & 0xFF) * 3)) {
 //          TRACEMS1(cinfo, 1, JTRC_JFIF_BADTHUMBNAILSIZE, cast(int) totallen);
         }
     } else if (datalen >= 6 &&
--- a/dwt/internal/image/JPEGEndOfImage.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/image/JPEGEndOfImage.d	Sat May 17 17:34:28 2008 +0200
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
  * Copyright (c) 2000, 2003 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
@@ -26,11 +26,11 @@
         super(reference);
     }
 
-    override public int signature() {
+    public override int signature() {
         return JPEGFileFormat.EOI;
     }
 
-    override public int fixedSize() {
+    public override int fixedSize() {
         return 2;
     }
 }
--- a/dwt/internal/image/JPEGFileFormat.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/image/JPEGFileFormat.d	Sat May 17 17:34:28 2008 +0200
@@ -25,10 +25,10 @@
 import dwt.internal.image.JPEGStartOfImage;
 import dwt.internal.image.JPEGDecoder;
 import dwt.internal.image.JPEGEndOfImage;
+import dwt.dwthelper.utils;
 
 import dwt.graphics.RGB;
 import dwt.graphics.PaletteData;
-import dwt.dwthelper.System;
 
 import tango.core.Exception;
 
@@ -150,39 +150,87 @@
     public static int[] CrRTable, CbBTable, CrGTable, CbGTable;
     public static int[] RYTable, GYTable, BYTable,
         RCbTable, GCbTable, BCbTable, RCrTable, GCrTable, BCrTable, NBitsTable;
+    //public static void static_this() {
+    static this() {
 
-    private static bool static_this_completed = false;
-    private static void static_this() {
-        if( static_this_completed ){
-            return;
+        RGB16 = [
+            new RGB(0,0,0),
+            new RGB(0x80,0,0),
+            new RGB(0,0x80,0),
+            new RGB(0x80,0x80,0),
+            new RGB(0,0,0x80),
+            new RGB(0x80,0,0x80),
+            new RGB(0,0x80,0x80),
+            new RGB(0xC0,0xC0,0xC0),
+            new RGB(0x80,0x80,0x80),
+            new RGB(0xFF,0,0),
+            new RGB(0,0xFF,0),
+            new RGB(0xFF,0xFF,0),
+            new RGB(0,0,0xFF),
+            new RGB(0xFF,0,0xFF),
+            new RGB(0,0xFF,0xFF),
+            new RGB(0xFF,0xFF,0xFF)
+        ];
+        int [] rYTable = new int[256];
+        int [] gYTable = new int[256];
+        int [] bYTable = new int[256];
+        int [] rCbTable = new int[256];
+        int [] gCbTable = new int[256];
+        int [] bCbTable = new int[256];
+        int [] rCrTable = new int[256];
+        int [] gCrTable = new int[256];
+        int [] bCrTable = new int[256];
+        for (int i = 0; i < 256; i++) {
+            rYTable[i] = i * 19595;
+            gYTable[i] = i * 38470;
+            bYTable[i] = i * 7471 + 32768;
+            rCbTable[i] = i * -11059;
+            gCbTable[i] = i * -21709;
+            bCbTable[i] = i * 32768 + 8388608;
+            gCrTable[i] = i * -27439;
+            bCrTable[i] = i * -5329;
         }
-        synchronized {
-            if( static_this_completed ){
-                return;
+        RYTable = rYTable;
+        GYTable = gYTable;
+        BYTable = bYTable;
+        RCbTable = rCbTable;
+        GCbTable = gCbTable;
+        BCbTable = bCbTable;
+        RCrTable = bCbTable;
+        GCrTable = gCrTable;
+        BCrTable = bCrTable;
+
+        /* Initialize YCbCr-RGB Tables */
+        int [] crRTable = new int[256];
+        int [] cbBTable = new int[256];
+        int [] crGTable = new int[256];
+        int [] cbGTable = new int[256];
+        for (int i = 0; i < 256; i++) {
+            int x2 = 2 * i - 255;
+            crRTable[i] = (45941 * x2 + 32768) >> 16;
+            cbBTable[i] = (58065 * x2 + 32768) >> 16;
+            crGTable[i] = -23401 * x2;
+            cbGTable[i] = -11277 * x2 + 32768;
+        }
+        CrRTable = crRTable;
+        CbBTable = cbBTable;
+        CrGTable = crGTable;
+        CbGTable = cbGTable;
+
+        /* Initialize BitCount Table */
+        int nBits = 1;
+        int power2 = 2;
+        int [] nBitsTable = new int[2048];
+        nBitsTable[0] = 0;
+        for (int i = 1; i < nBitsTable.length; i++) {
+            if (!(i < power2)) {
+                nBits++;
+                power2 *= 2;
             }
-            initialize();
-            RGB16 = [
-                new RGB(0,0,0),
-                new RGB(0x80,0,0),
-                new RGB(0,0x80,0),
-                new RGB(0x80,0x80,0),
-                new RGB(0,0,0x80),
-                new RGB(0x80,0,0x80),
-                new RGB(0,0x80,0x80),
-                new RGB(0xC0,0xC0,0xC0),
-                new RGB(0x80,0x80,0x80),
-                new RGB(0xFF,0,0),
-                new RGB(0,0xFF,0),
-                new RGB(0xFF,0xFF,0),
-                new RGB(0,0,0xFF),
-                new RGB(0xFF,0,0xFF),
-                new RGB(0,0xFF,0xFF),
-                new RGB(0xFF,0xFF,0xFF)
-            ];
-            static_this_completed = true;
+            nBitsTable[i] = nBits;
         }
+        NBitsTable = nBitsTable;
     }
-
 void compress(ImageData image, byte[] dataYComp, byte[] dataCbComp, byte[] dataCrComp) {
     int srcWidth = image.width;
     int srcHeight = image.height;
@@ -240,15 +288,15 @@
             int delta = componentWidth - compressedWidth;
             for (int yPos = 0; yPos < compressedHeight; yPos++) {
                 int dstOfs = ((yPos + 1) * componentWidth - delta);
-                int dataValue = imageComponent[dstOfs - 1] & 0xFF;
+                int dataValue = imageComponent[(dstOfs > 0) ? dstOfs - 1 : 0] & 0xFF;
                 for (int i = 0; i < delta; i++) {
                     imageComponent[dstOfs + i] = cast(byte)dataValue;
                 }
             }
         }
         if (compressedHeight < componentHeight) {
-            int srcOfs = (compressedHeight - 1) * componentWidth;
-            for (int yPos = compressedHeight; yPos <= componentHeight; yPos++) {
+            int srcOfs = (compressedHeight > 0) ? (compressedHeight - 1) * componentWidth : 1;
+            for (int yPos = (compressedHeight > 0) ? compressedHeight : 1; yPos <= componentHeight; yPos++) {
                 int dstOfs = (yPos - 1) * componentWidth;
                 System.arraycopy(imageComponent, srcOfs, imageComponent, dstOfs, componentWidth);
             }
@@ -1171,58 +1219,6 @@
     }
     restartInterval = dri.getRestartInterval();
 }
-static void initialize() {
-    initializeRGBYCbCrTables();
-    initializeYCbCrRGBTables();
-    initializeBitCountTable();
-}
-static void initializeBitCountTable() {
-    int nBits = 1;
-    int power2 = 2;
-    NBitsTable = new int[2048];
-    NBitsTable[0] = 0;
-    for (int i = 1; i < NBitsTable.length; i++) {
-        if (!(i < power2)) {
-            nBits++;
-            power2 *= 2;
-        }
-        NBitsTable[i] = nBits;
-    }
-}
-static void initializeRGBYCbCrTables() {
-    RYTable = new int[256];
-    GYTable = new int[256];
-    BYTable = new int[256];
-    RCbTable = new int[256];
-    GCbTable = new int[256];
-    BCbTable = new int[256];
-    RCrTable = BCbTable;
-    GCrTable = new int[256];
-    BCrTable = new int[256];
-    for (int i = 0; i < 256; i++) {
-        RYTable[i] = i * 19595;
-        GYTable[i] = i * 38470;
-        BYTable[i] = i * 7471 + 32768;
-        RCbTable[i] = i * -11059;
-        GCbTable[i] = i * -21709;
-        BCbTable[i] = i * 32768 + 8388608;
-        GCrTable[i] = i * -27439;
-        BCrTable[i] = i * -5329;
-    }
-}
-static void initializeYCbCrRGBTables() {
-    CrRTable = new int[256];
-    CbBTable = new int[256];
-    CrGTable = new int[256];
-    CbGTable = new int[256];
-    for (int i = 0; i < 256; i++) {
-        int x2 = 2 * i - 255;
-        CrRTable[i] = (45941 * x2 + 32768) >> 16;
-        CbBTable[i] = (58065 * x2 + 32768) >> 16;
-        CrGTable[i] = -23401 * x2;
-        CbGTable[i] = -11277 * x2 + 32768;
-    }
-}
 void inverseDCT(int[] dataUnit) {
     for (int row = 0; row < 8; row++) {
         int rIndex = row * DCTSIZE;
--- a/dwt/internal/image/JPEGFixedSizeSegment.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/image/JPEGFixedSizeSegment.d	Sat May 17 17:34:28 2008 +0200
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
  * Copyright (c) 2000, 2003 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
@@ -42,10 +42,10 @@
 
     abstract public int fixedSize();
 
-    override public int getSegmentLength() {
+    public override int getSegmentLength() {
         return fixedSize() - 2;
     }
 
-    override public void setSegmentLength(int length) {
+    public override void setSegmentLength(int length) {
     }
 }
--- a/dwt/internal/image/JPEGFrameHeader.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/image/JPEGFrameHeader.d	Sat May 17 17:34:28 2008 +0200
@@ -17,7 +17,7 @@
 import dwt.internal.image.JPEGVariableSizeSegment;
 import dwt.internal.image.JPEGFileFormat;
 import dwt.internal.image.LEDataInputStream;
-import dwt.dwthelper.System;
+import dwt.dwthelper.utils;
 
 final class JPEGFrameHeader : JPEGVariableSizeSegment {
     int maxVFactor;
@@ -198,7 +198,7 @@
      *  SOF_14 - Differential progressive, arithmetic coding
      *  SOF_15 - Differential lossless, arithmetic coding
      */
-    override public bool verify() {
+    public override bool verify() {
         int marker = getSegmentMarker();
         return (marker >= JPEGFileFormat.SOF0 && marker <= JPEGFileFormat.SOF3) ||
             (marker >= JPEGFileFormat.SOF5 && marker <= JPEGFileFormat.SOF7) ||
--- a/dwt/internal/image/JPEGHuffmanTable.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/image/JPEGHuffmanTable.d	Sat May 17 17:34:28 2008 +0200
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
  * Copyright (c) 2000, 2005 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
@@ -264,7 +264,7 @@
     System.arraycopy(huffTables, 0, allTables, 0, huffTableCount);
 }
 
-override public int signature() {
+public override int signature() {
     return JPEGFileFormat.DHT;
 }
 }
--- a/dwt/internal/image/JPEGQuantizationTable.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/image/JPEGQuantizationTable.d	Sat May 17 17:34:28 2008 +0200
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
  * Copyright (c) 2000, 2006 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
@@ -166,7 +166,7 @@
     }
 }
 
-override public int signature() {
+public override int signature() {
     return JPEGFileFormat.DQT;
 }
 }
--- a/dwt/internal/image/JPEGRestartInterval.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/image/JPEGRestartInterval.d	Sat May 17 17:34:28 2008 +0200
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
  * Copyright (c) 2000, 2003 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
@@ -22,7 +22,7 @@
         super(byteStream);
     }
 
-    override public int signature() {
+    public override int signature() {
         return JPEGFileFormat.DRI;
     }
 
@@ -30,7 +30,7 @@
         return ((reference[4] & 0xFF) << 8 | (reference[5] & 0xFF));
     }
 
-    override public int fixedSize() {
+    public override int fixedSize() {
         return 6;
     }
 }
--- a/dwt/internal/image/JPEGScanHeader.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/image/JPEGScanHeader.d	Sat May 17 17:34:28 2008 +0200
@@ -16,7 +16,7 @@
 import dwt.internal.image.JPEGVariableSizeSegment;
 import dwt.internal.image.LEDataInputStream;
 import dwt.internal.image.JPEGFileFormat;
-import dwt.dwthelper.System;
+import dwt.dwthelper.utils;
 
 final class JPEGScanHeader : JPEGVariableSizeSegment {
     public int[][] componentParameters;
@@ -95,7 +95,7 @@
     reference[(2 * getNumberOfImageComponents()) + 5] = cast(byte)anInteger;
 }
 
-override public int signature() {
+public override int signature() {
     return JPEGFileFormat.SOS;
 }
 
--- a/dwt/internal/image/JPEGStartOfImage.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/image/JPEGStartOfImage.d	Sat May 17 17:34:28 2008 +0200
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
  * Copyright (c) 2000, 2003 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
@@ -30,11 +30,11 @@
         super(byteStream);
     }
 
-    override public int signature() {
+    public override int signature() {
         return JPEGFileFormat.SOI;
     }
 
-    override public int fixedSize() {
+    public override int fixedSize() {
         return 2;
     }
 }
--- a/dwt/internal/image/LEDataInputStream.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/image/LEDataInputStream.d	Sat May 17 17:34:28 2008 +0200
@@ -51,7 +51,7 @@
         else throw new IllegalArgumentException("bufferSize must be greater zero" );
     }
 
-    override public void close() {
+    public void close() {
         buf = null;
         if (host !is null) {
             host.close();
@@ -69,7 +69,7 @@
     /**
      * Answers how many bytes are available for reading without blocking
      */
-    override public int available() {
+    public override int available() {
         if (buf is null) throw new IOException("buf is null");
         return (buf.length - pos) + host.available();
     }
@@ -77,7 +77,7 @@
     /**
      * Answer the next byte of the input stream.
      */
-    override public int read() {
+    public override int read() {
         if (buf is null) throw new IOException("buf is null");
         if (pos < buf.length) {
             position++;
@@ -92,15 +92,15 @@
      * Don't imitate the JDK behaviour of reading a random number
      * of bytes when you can actually read them all.
      */
-    override public int read(byte b[], int off, int len) {
-        int read_ = 0, count;
-        while (read_ !is len && (count = readData(b, off, len - read_)) !is -1) {
+    public override int read(byte b[], int off, int len) {
+        int read = 0, count;
+        while (read !is len && (count = readData(b, off, len - read)) !is -1) {
             off += count;
-            read_ += count;
+            read += count;
         }
-        position += read_;
-        if (read_ is 0 && read_ !is len) return -1;
-        return read_;
+        position += read;
+        if (read is 0 && read !is len) return -1;
+        return read;
     }
 
     /**
@@ -143,6 +143,7 @@
         if (cacheCopied is len) return len;
 
         int inCopied = host.read( buffer, newOffset, len - cacheCopied );
+        if( inCopied is -1 ) inCopied = -1;
         if (inCopied > 0 ) return inCopied + cacheCopied;
         if (cacheCopied is 0) return inCopied;
         return cacheCopied;
@@ -155,9 +156,9 @@
     public int readInt() {
         byte[4] buf = void;
         read(buf);
-        return ((((((buf[3] & 0xFF) << 24) |
-            (buf[2] & 0xFF)) << 16) |
-            (buf[1] & 0xFF)) << 8) |
+        return ((buf[3] & 0xFF) << 24) | 
+            ((buf[2] & 0xFF) << 16) | 
+            ((buf[1] & 0xFF) << 8) | 
             (buf[0] & 0xFF);
     }
 
--- a/dwt/internal/image/LEDataOutputStream.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/image/LEDataOutputStream.d	Sat May 17 17:34:28 2008 +0200
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
  * Copyright (c) 2000, 2005 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
@@ -16,8 +16,11 @@
 import dwt.dwthelper.OutputStream;
 
 final class LEDataOutputStream : OutputStream {
+
     alias OutputStream.write write;
+
     OutputStream ostr;
+
 public this(OutputStream output) {
     this.ostr = output;
 }
@@ -25,13 +28,13 @@
  * Write the specified number of bytes of the given byte array,
  * starting at the specified offset, to the output stream.
  */
-override public void write(byte b[], int off, int len) {
+public override void write(byte b[], int off, int len) {
     ostr.write(b, off, len);
 }
 /**
  * Write the given byte to the output stream.
  */
-override public void write(int b)  {
+public override void write(int b)  {
     ostr.write(b);
 }
 /**
--- a/dwt/internal/image/LZWCodec.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/image/LZWCodec.d	Sat May 17 17:34:28 2008 +0200
@@ -20,9 +20,9 @@
 import dwt.graphics.ImageData;
 import dwt.graphics.ImageLoader;
 import dwt.graphics.ImageLoaderEvent;
+import dwt.dwthelper.utils;
 
 import tango.core.Exception;
-import dwt.dwthelper.System;
 
 final class LZWCodec {
     int bitsPerPixel, blockSize, blockIndex, currentByte, bitsLeft,
--- a/dwt/internal/image/OS2BMPFileFormat.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/image/OS2BMPFileFormat.d	Sat May 17 17:34:28 2008 +0200
@@ -20,9 +20,9 @@
 import dwt.internal.image.LEDataInputStream;
 import dwt.internal.image.FileFormat;
 import dwt.dwthelper.ByteArrayOutputStream;
+import dwt.dwthelper.utils;
 
 import tango.core.Exception;
-import dwt.dwthelper.System;
 
 final class OS2BMPFileFormat : FileFormat {
     static final int BMPFileHeaderSize = 14;
--- a/dwt/internal/image/PNGFileFormat.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/image/PNGFileFormat.d	Sat May 17 17:34:28 2008 +0200
@@ -29,9 +29,9 @@
 import dwt.internal.image.PngEncoder;
 import dwt.internal.image.PngInputStream;
 import dwt.internal.image.PngDecodingDataStream;
+import dwt.dwthelper.utils;
 
 import dwt.dwthelper.BufferedInputStream;
-import dwt.dwthelper.System;
 
 import tango.core.Exception;
 
@@ -176,7 +176,7 @@
         if ((signature[4] & 0xFF) !is 13) return false; //<RETURN>
         if ((signature[5] & 0xFF) !is 10) return false; //<LINEFEED>
         if ((signature[6] & 0xFF) !is 26) return false; //<CTRL/Z>
-        if ((signature[7] & 0xFF) !is 10) return false; //<LINEFEED>
+        if ((signature[7] & 0xFF) !is 10) return false; //<LINEFEED>        
         return true;
     } catch (Exception e) {
         return false;
@@ -314,7 +314,7 @@
     bool use3_2 = true;//System.getProperty("dwt.internal.image.PNGFileFormat_3.2") !is null;
     InputStream inflaterStream = use3_2 ? null : Compatibility.newInflaterInputStream(stream);
     if (inflaterStream !is null) {
-        stream = new BufferedInputStream(inflaterStream);
+        stream = inflaterStream;
     } else {
         stream = new PngDecodingDataStream(stream);
     }
--- a/dwt/internal/image/PngChunk.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/image/PngChunk.d	Sat May 17 17:34:28 2008 +0200
@@ -21,11 +21,10 @@
 import dwt.internal.image.PngIdatChunk;
 import dwt.internal.image.PngIendChunk;
 import dwt.internal.image.PngTrnsChunk;
+import dwt.dwthelper.utils;
 
 import tango.core.Exception;
 import tango.text.convert.Format;
-import dwt.dwthelper.System;
-import dwt.dwthelper.utils;
 
 class PngChunk {
     byte[] reference;
@@ -53,28 +52,19 @@
     static const byte[] TYPE_IEND = cast(byte[])"IEND";//{(byte) 'I', (byte) 'E', (byte) 'N', (byte) 'D'};
     static const byte[] TYPE_tRNS = cast(byte[])"tRNS";//{(byte) 't', (byte) 'R', (byte) 'N', (byte) 'S'};
 
-    private static /+const+/ int[] CRC_TABLE;
-    private static bool static_this_completed = false;
-    private static void static_this() {
-        if( static_this_completed ){
-            return;
-        }
-        synchronized {
-            if( static_this_completed ){
-                return;
-            }
-            CRC_TABLE = new int[256];
-            for (int i = 0; i < 256; i++) {
-                CRC_TABLE[i] = i;
-                for (int j = 0; j < 8; j++) {
-                    if ((CRC_TABLE[i] & 0x1) is 0) {
-                        CRC_TABLE[i] = (CRC_TABLE[i] >> 1) & 0x7FFFFFFF;
-                    } else {
-                        CRC_TABLE[i] = 0xEDB88320 ^ ((CRC_TABLE[i] >> 1) & 0x7FFFFFFF);
-                    }
+    static const int[] CRC_TABLE;
+    //public static void static_this() {
+    static this() {
+        CRC_TABLE = new int[256];
+        for (int i = 0; i < 256; i++) {
+            CRC_TABLE[i] = i;
+            for (int j = 0; j < 8; j++) {
+                if ((CRC_TABLE[i] & 0x1) is 0) {
+                    CRC_TABLE[i] = (CRC_TABLE[i] >> 1) & 0x7FFFFFFF;
+                } else {
+                    CRC_TABLE[i] = 0xEDB88320 ^ ((CRC_TABLE[i] >> 1) & 0x7FFFFFFF);
                 }
             }
-            static_this_completed = true;
         }
     }
 
@@ -85,7 +75,6 @@
  * given.
  */
 this(byte[] reference) {
-    static_this();
     setReference(reference);
     if (reference.length < LENGTH_OFFSET + LENGTH_FIELD_LENGTH) DWT.error(DWT.ERROR_INVALID_IMAGE);
     length = getInt32(LENGTH_OFFSET);
@@ -385,7 +374,7 @@
  *
  * @return a string representation of the event
  */
-override public String toString() {
+public override String toString() {
     String buffer = Format( "{\n\tLength: {}\n\tType: {}{}\n\tCRC: {:X}\n}",
         getLength(),
         cast(String) getTypeBytes(),
--- a/dwt/internal/image/PngDecodingDataStream.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/image/PngDecodingDataStream.d	Sat May 17 17:34:28 2008 +0200
@@ -19,7 +19,9 @@
 import dwt.internal.image.PngLzBlockReader;
 
 public class PngDecodingDataStream : InputStream {
+
     alias InputStream.read read;
+
     InputStream stream;
     byte currentByte;
     int nextBitIndex;
@@ -51,7 +53,7 @@
     lzBlockReader.assertCompressedDataAtEnd();
 }
 
-override public void close() {
+public override void close() {
     assertImageDataAtEnd();
     checkAdler();
 }
--- a/dwt/internal/image/PngDeflater.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/image/PngDeflater.d	Sat May 17 17:34:28 2008 +0200
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
  * Copyright (c) 2000, 2006 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
@@ -36,7 +36,6 @@
     int nextWindow;
 
 public this(){
-    static_this();
     bytes = new ByteArrayOutputStream(1024);
 }
 
@@ -56,7 +55,7 @@
 
 }
 
-class Match {
+static class Match {
 
     int length, distance;
 
@@ -121,82 +120,72 @@
 
 }
 
-private static /+const+/ Code lengthCodes[];
-private static /+const+/ Code distanceCodes[];
+static const Code lengthCodes[];
+static const Code distanceCodes[];
 
-private static bool static_this_completed = false;
-private static void static_this() {
-    if( static_this_completed ){
-        return;
-    }
-    synchronized {
-        if( static_this_completed ){
-            return;
-        }
-        lengthCodes = [
-            new Code(257, 0, 3, 3),
-            new Code(258, 0, 4, 4),
-            new Code(259, 0, 5, 5),
-            new Code(260, 0, 6, 6),
-            new Code(261, 0, 7, 7),
-            new Code(262, 0, 8, 8),
-            new Code(263, 0, 9, 9),
-            new Code(264, 0, 10, 10),
-            new Code(265, 1, 11, 12),
-            new Code(266, 1, 13, 14),
-            new Code(267, 1, 15, 16),
-            new Code(268, 1, 17, 18),
-            new Code(269, 2, 19, 22),
-            new Code(270, 2, 23, 26),
-            new Code(271, 2, 27, 30),
-            new Code(272, 2, 31, 34),
-            new Code(273, 3, 35, 42),
-            new Code(274, 3, 43, 50),
-            new Code(275, 3, 51, 58),
-            new Code(276, 3, 59, 66),
-            new Code(277, 4, 67, 82),
-            new Code(278, 4, 83, 98),
-            new Code(279, 4, 99, 114),
-            new Code(280, 4, 115, 130),
-            new Code(281, 5, 131, 162),
-            new Code(282, 5, 163, 194),
-            new Code(283, 5, 195, 226),
-            new Code(284, 5, 227, 257),
-            new Code(285, 0, 258, 258)];
+static this() {
+    lengthCodes = [
+        new Code(257, 0, 3, 3),
+        new Code(258, 0, 4, 4),
+        new Code(259, 0, 5, 5),
+        new Code(260, 0, 6, 6),
+        new Code(261, 0, 7, 7),
+        new Code(262, 0, 8, 8),
+        new Code(263, 0, 9, 9),
+        new Code(264, 0, 10, 10),
+        new Code(265, 1, 11, 12),
+        new Code(266, 1, 13, 14),
+        new Code(267, 1, 15, 16),
+        new Code(268, 1, 17, 18),
+        new Code(269, 2, 19, 22),
+        new Code(270, 2, 23, 26),
+        new Code(271, 2, 27, 30),
+        new Code(272, 2, 31, 34),
+        new Code(273, 3, 35, 42),
+        new Code(274, 3, 43, 50),
+        new Code(275, 3, 51, 58),
+        new Code(276, 3, 59, 66),
+        new Code(277, 4, 67, 82),
+        new Code(278, 4, 83, 98),
+        new Code(279, 4, 99, 114),
+        new Code(280, 4, 115, 130),
+        new Code(281, 5, 131, 162),
+        new Code(282, 5, 163, 194),
+        new Code(283, 5, 195, 226),
+        new Code(284, 5, 227, 257),
+        new Code(285, 0, 258, 258)];
 
-        distanceCodes = [
-            new Code(0, 0, 1, 1),
-            new Code(1, 0, 2, 2),
-            new Code(2, 0, 3, 3),
-            new Code(3, 0, 4, 4),
-            new Code(4, 1, 5, 6),
-            new Code(5, 1, 7, 8),
-            new Code(6, 2, 9, 12),
-            new Code(7, 2, 13, 16),
-            new Code(8, 3, 17, 24),
-            new Code(9, 3, 25, 32),
-            new Code(10, 4, 33, 48),
-            new Code(11, 4, 49, 64),
-            new Code(12, 5, 65, 96),
-            new Code(13, 5, 97, 128),
-            new Code(14, 6, 129, 192),
-            new Code(15, 6, 193, 256),
-            new Code(16, 7, 257, 384),
-            new Code(17, 7, 385, 512),
-            new Code(18, 8, 513, 768),
-            new Code(19, 8, 769, 1024),
-            new Code(20, 9, 1025, 1536),
-            new Code(21, 9, 1537, 2048),
-            new Code(22, 10, 2049, 3072),
-            new Code(23, 10, 3073, 4096),
-            new Code(24, 11, 4097, 6144),
-            new Code(25, 11, 6145, 8192),
-            new Code(26, 12, 8193, 12288),
-            new Code(27, 12, 12289, 16384),
-            new Code(28, 13, 16385, 24576),
-            new Code(29, 13, 24577, 32768)];
-        static_this_completed = true;
-    }
+    distanceCodes = [
+        new Code(0, 0, 1, 1),
+        new Code(1, 0, 2, 2),
+        new Code(2, 0, 3, 3),
+        new Code(3, 0, 4, 4),
+        new Code(4, 1, 5, 6),
+        new Code(5, 1, 7, 8),
+        new Code(6, 2, 9, 12),
+        new Code(7, 2, 13, 16),
+        new Code(8, 3, 17, 24),
+        new Code(9, 3, 25, 32),
+        new Code(10, 4, 33, 48),
+        new Code(11, 4, 49, 64),
+        new Code(12, 5, 65, 96),
+        new Code(13, 5, 97, 128),
+        new Code(14, 6, 129, 192),
+        new Code(15, 6, 193, 256),
+        new Code(16, 7, 257, 384),
+        new Code(17, 7, 385, 512),
+        new Code(18, 8, 513, 768),
+        new Code(19, 8, 769, 1024),
+        new Code(20, 9, 1025, 1536),
+        new Code(21, 9, 1537, 2048),
+        new Code(22, 10, 2049, 3072),
+        new Code(23, 10, 3073, 4096),
+        new Code(24, 11, 4097, 6144),
+        new Code(25, 11, 6145, 8192),
+        new Code(26, 12, 8193, 12288),
+        new Code(27, 12, 12289, 16384),
+        new Code(28, 13, 16385, 24576),
+        new Code(29, 13, 24577, 32768)];
 }
 
 void writeShortLSB(ByteArrayOutputStream baos, int theShort) {
--- a/dwt/internal/image/PngEncoder.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/image/PngEncoder.d	Sat May 17 17:34:28 2008 +0200
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
  * Copyright (c) 2000, 2006 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
@@ -15,10 +15,12 @@
 import dwt.internal.image.LEDataOutputStream;
 import dwt.internal.image.PngDeflater;
 import dwt.dwthelper.ByteArrayOutputStream;
+import dwt.dwthelper.OutputStream;
 import dwt.DWT;
 import dwt.graphics.ImageData;
 import dwt.graphics.ImageLoader;
 import dwt.graphics.RGB;
+import dwt.internal.Compatibility;
 import dwt.internal.image.PngChunk;
 
 import tango.core.Exception;
@@ -236,21 +238,23 @@
 void writeImageData() {
 
     ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
+    OutputStream os = Compatibility.newDeflaterOutputStream(baos);
+    if (os is null) os = baos;
 
     if (colorType is 3) {
 
-        int[] lineData = new int[width];
+        byte[] lineData = new byte[width];
 
         for (int y = 0; y < height; y++) {
 
-            byte filter[] = [0];
-            baos.write(filter, 0, 1);
+            int filter = 0;
+            os.write(filter);
 
             data.getPixels(0, y, width, lineData, 0);
 
             for (int x = 0; x < lineData.length; x++) {
 
-                baos.write(cast(byte) lineData[x]);
+                os.write(lineData[x]);
 
             }
 
@@ -261,7 +265,10 @@
     else {
 
         int[] lineData = new int[width];
-        byte[] alphaData = new byte[width];
+        byte[] alphaData = null;
+        if (colorType is 6) {
+            alphaData = new byte[width];
+        }
 
         int redMask = data.palette.redMask;
         int redShift = data.palette.redShift;
@@ -272,8 +279,8 @@
 
         for (int y = 0; y < height; y++) {
 
-            byte filter[] = [0];
-            baos.write(filter, 0, 1);
+            int filter = 0;
+            os.write(filter);
 
             data.getPixels(0, y, width, lineData, 0);
 
@@ -292,14 +299,12 @@
                 int b = pixel & blueMask;
                 b = (blueShift < 0) ? b >>> -blueShift : b << blueShift;
 
-                byte pixels[] = [cast(byte) r, cast(byte) g, cast(byte) b];
-                baos.write(pixels, 0, 3);
+                os.write(r);
+                os.write(g);
+                os.write(b);
 
                 if (colorType is 6) {
-
-                    byte alpha[] = [alphaData[x]];
-                    baos.write(alpha, 0, 1);
-
+                    os.write(alphaData[x]);
                 }
 
             }
@@ -308,8 +313,14 @@
 
     }
 
-    PngDeflater deflater = new PngDeflater();
-    byte[] compressed = deflater.deflate(baos.toByteArray());
+    os.flush();
+    os.close();
+
+    byte[] compressed = baos.toByteArray();
+    if (os is baos) {
+        PngDeflater deflater = new PngDeflater();
+        compressed = deflater.deflate(compressed);
+    }
 
     writeChunk(TAG_IDAT, compressed);
 
--- a/dwt/internal/image/PngHuffmanTable.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/image/PngHuffmanTable.d	Sat May 17 17:34:28 2008 +0200
@@ -116,7 +116,7 @@
     return codeValues[index];
 }
 
-class CodeLengthInfo {
+static class CodeLengthInfo {
     int length;
     int max;
     int min;
--- a/dwt/internal/image/PngIdatChunk.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/image/PngIdatChunk.d	Sat May 17 17:34:28 2008 +0200
@@ -17,7 +17,7 @@
 import dwt.internal.image.PngFileReadState;
 import dwt.internal.image.PngIhdrChunk;
 import dwt.internal.image.PngChunk;
-import dwt.dwthelper.System;
+import dwt.dwthelper.utils;
 
 class PngIdatChunk : PngChunk {
 
--- a/dwt/internal/image/PngIhdrChunk.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/image/PngIhdrChunk.d	Sat May 17 17:34:28 2008 +0200
@@ -12,6 +12,8 @@
  *******************************************************************************/
 module dwt.internal.image.PngIhdrChunk;
 
+import dwt.dwthelper.utils;
+
 
 import dwt.DWT;
 import dwt.graphics.PaletteData;
@@ -20,7 +22,6 @@
 import dwt.internal.image.PngIhdrChunk;
 import dwt.internal.image.PngChunk;
 import tango.text.convert.Format;
-import dwt.dwthelper.utils;
 
 class PngIhdrChunk : PngChunk {
     static const int IHDR_DATA_LENGTH = 13;
--- a/dwt/internal/image/PngInputStream.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/image/PngInputStream.d	Sat May 17 17:34:28 2008 +0200
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
  * Copyright (c) 2000, 2006 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
@@ -22,6 +22,7 @@
 import Math = tango.math.Math;
 
 public class PngInputStream : InputStream {
+
     alias InputStream.read read;
 
     PngChunkReader reader;
--- a/dwt/internal/image/PngPlteChunk.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/image/PngPlteChunk.d	Sat May 17 17:34:28 2008 +0200
@@ -12,6 +12,8 @@
  *******************************************************************************/
 module dwt.internal.image.PngPlteChunk;
 
+import dwt.dwthelper.utils;
+
 
 import dwt.DWT;
 import dwt.graphics.PaletteData;
@@ -21,7 +23,6 @@
 import dwt.internal.image.PngIhdrChunk;
 
 import tango.text.convert.Format;
-import dwt.dwthelper.utils;
 
 class PngPlteChunk : PngChunk {
 
@@ -111,7 +112,7 @@
 
     // Palette chunks' data fields must be event multiples
     // of 3. Each 3-byte group represents an RGB value.
-    if (getLength() % 3 !is 0) DWT.error(DWT.ERROR_INVALID_IMAGE);
+    if (getLength() % 3 !is 0) DWT.error(DWT.ERROR_INVALID_IMAGE);  
 
     // Palettes cannot have more entries than 2^bitDepth
     // where bitDepth is the bit depth of the image given
--- a/dwt/internal/image/PngTrnsChunk.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/image/PngTrnsChunk.d	Sat May 17 17:34:28 2008 +0200
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
  * Copyright (c) 2000, 2006 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
--- a/dwt/internal/image/TIFFDirectory.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/image/TIFFDirectory.d	Sat May 17 17:34:28 2008 +0200
@@ -22,7 +22,6 @@
 import dwt.graphics.RGB;
 import dwt.DWT;
 import dwt.dwthelper.utils;
-import dwt.dwthelper.System;
 
 final class TIFFDirectory {
 
--- a/dwt/internal/image/TIFFFileFormat.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/image/TIFFFileFormat.d	Sat May 17 17:34:28 2008 +0200
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/*******************************************************************************
  * Copyright (c) 2000, 2005 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
--- a/dwt/internal/image/WinBMPFileFormat.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/image/WinBMPFileFormat.d	Sat May 17 17:34:28 2008 +0200
@@ -12,15 +12,15 @@
  *******************************************************************************/
 module dwt.internal.image.WinBMPFileFormat;
 
-public import dwt.internal.image.FileFormat;
-public import dwt.graphics.PaletteData;
+import dwt.internal.image.FileFormat;
+import dwt.graphics.PaletteData;
 import dwt.graphics.Point;
 import dwt.graphics.RGB;
 import dwt.dwthelper.ByteArrayOutputStream;
 import dwt.DWT;
+import dwt.dwthelper.utils;
 
 import tango.core.Exception;
-import dwt.dwthelper.System;
 
 final class WinBMPFileFormat : FileFormat {
 
--- a/dwt/internal/image/WinICOFileFormat.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/image/WinICOFileFormat.d	Sat May 17 17:34:28 2008 +0200
@@ -12,15 +12,15 @@
  *******************************************************************************/
 module dwt.internal.image.WinICOFileFormat;
 
-public import dwt.internal.image.FileFormat;
-public import dwt.graphics.PaletteData;
+import dwt.internal.image.FileFormat;
+import dwt.graphics.PaletteData;
 import dwt.internal.image.WinBMPFileFormat;
 import dwt.DWT;
+import dwt.dwthelper.utils;
 
 import tango.core.Exception;
-import dwt.dwthelper.System;
 
-final class WinICOFileFormat : FileFormat {
+public final class WinICOFileFormat : FileFormat {
 
 byte[] bitInvertData(byte[] data, int startIndex, int endIndex) {
     // Destructively bit invert data in the given byte array.
--- a/dwt/internal/ole/win32/COM.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/ole/win32/COM.d	Sat May 17 17:34:28 2008 +0200
@@ -75,7 +75,7 @@
     public static const GUID IIDIAdviseSink = IIDFromStringT!("{0000010F-0000-0000-C000-000000000046}"); //$NON-NLS-1$
     //public static const GUID IIDIAdviseSink2 = IIDFromStringT!("{00000125-0000-0000-C000-000000000046}"); //$NON-NLS-1$
     //public static const GUID IIDIBindCtx = IIDFromStringT!("{0000000E-0000-0000-C000-000000000046}"); //$NON-NLS-1$
-    //public static const GUID IIDIClassFactory = IIDFromStringT!("{00000001-0000-0000-C000-000000000046}"); //$NON-NLS-1$
+    public static const GUID IIDIClassFactory = IIDFromStringT!("{00000001-0000-0000-C000-000000000046}"); //$NON-NLS-1$
     public static const GUID IIDIClassFactory2 = IIDFromStringT!("{B196B28F-BAB4-101A-B69C-00AA00341D07}"); //$NON-NLS-1$
     public static const GUID IIDIConnectionPoint = IIDFromStringT!("{B196B286-BAB4-101A-B69C-00AA00341D07}"); //$NON-NLS-1$
     public static const GUID IIDIConnectionPointContainer = IIDFromStringT!("{B196B284-BAB4-101A-B69C-00AA00341D07}"); //$NON-NLS-1$
@@ -250,13 +250,18 @@
     public static const int DISPID_FONT_WEIGHT = 7;
     public static const int DISPID_FORECOLOR = -513;
     public static const int DISPID_HTMLDOCUMENTEVENTS_ONDBLCLICK = 0xFFFFFDA7;
+    public static const int DISPID_HTMLDOCUMENTEVENTS_ONDRAGEND = 0x80010015;
     public static const int DISPID_HTMLDOCUMENTEVENTS_ONDRAGSTART = 0x8001000B;
+    public static const int DISPID_HTMLDOCUMENTEVENTS_ONKEYDOWN = 0xFFFFFDA6;
+    public static const int DISPID_HTMLDOCUMENTEVENTS_ONKEYPRESS = 0xFFFFFDA5;
+    public static const int DISPID_HTMLDOCUMENTEVENTS_ONKEYUP = 0xFFFFFDA4;
     public static const int DISPID_HTMLDOCUMENTEVENTS_ONMOUSEOUT = 0x80010009;
     public static const int DISPID_HTMLDOCUMENTEVENTS_ONMOUSEOVER = 0x80010008;
     public static const int DISPID_HTMLDOCUMENTEVENTS_ONMOUSEMOVE = 0xFFFFFDA2;
     public static const int DISPID_HTMLDOCUMENTEVENTS_ONMOUSEDOWN = 0xFFFFFDA3;
     public static const int DISPID_HTMLDOCUMENTEVENTS_ONMOUSEUP = 0xFFFFFDA1;
     public static const int DISPID_HTMLDOCUMENTEVENTS_ONSTOP = 0x00000402;
+    public static const int DISPID_HTMLDOCUMENTEVENTS_ONMOUSEWHEEL = 1033;
 
     //public static const int DISPID_READYSTATE = -525;
     //public static const int DISPID_READYSTATECHANGE = -609;
@@ -268,6 +273,7 @@
     public static const int DROPEFFECT_MOVE = 2;
     public static const int DROPEFFECT_LINK = 4;
     public static const int DROPEFFECT_SCROLL = 0x80000000;
+    public static final int DSH_ALLOWDROPDESCRIPTIONTEXT = 0x1;
     public static const int DV_E_FORMATETC = -2147221404;
     public static const int DV_E_STGMEDIUM = -2147221402;
     public static const int DV_E_TYMED = -2147221399;
@@ -483,6 +489,7 @@
 alias COMAPI.RegisterDragDrop RegisterDragDrop;
 alias COMAPI.ReleaseStgMedium ReleaseStgMedium;
 alias COMAPI.RevokeDragDrop RevokeDragDrop;
+alias COMAPI.SHDoDragDrop SHDoDragDrop;
 alias COMAPI.StgCreateDocfile StgCreateDocfile;
 alias COMAPI.StgIsStorageFile StgIsStorageFile;
 alias COMAPI.StgOpenStorage StgOpenStorage;
@@ -814,7 +821,7 @@
 public static const int STATE_SYSTEM_FOCUSED = 0x4;
 public static const int STATE_SYSTEM_PRESSED = 0x8;
 public static const int STATE_SYSTEM_CHECKED = 0x10;
-//public static const int STATE_SYSTEM_MIXED = 0x20;
+public static const int STATE_SYSTEM_MIXED = 0x20;
 //public static const int STATE_SYSTEM_INDETERMINATE = STATE_SYSTEM_MIXED;
 public static const int STATE_SYSTEM_READONLY = 0x40;
 public static const int STATE_SYSTEM_HOTTRACKED = 0x80;
--- a/dwt/internal/ole/win32/COMAPI.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/ole/win32/COMAPI.d	Sat May 17 17:34:28 2008 +0200
@@ -207,6 +207,13 @@
 WINOLEAPI RevokeDragDrop(
   HWND hwnd  //Handle to a window that can accept drops
 );
+HRESULT SHDoDragDrop(
+    HWND hwnd,
+    IDataObject *pdtobj,
+    IDropSource *pdsrc,
+    DWORD dwEffect,
+    DWORD *pdwEffect
+);
 HRESULT StgCreateDocfile(
   WCHAR* pwcsName,
   DWORD grfMode,
--- a/dwt/internal/win32/OS.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/win32/OS.d	Sat May 17 17:34:28 2008 +0200
@@ -22,7 +22,7 @@
 import tango.sys.Common : SysError;
 static import tango.stdc.stdlib;
 
-import tango.stdc.string : memset;
+import tango.stdc.string : memset, strlen;
 import tango.stdc.stringz : toString16z;
 import tango.text.convert.Utf : toString16;
 import tango.io.FilePath;
@@ -448,6 +448,7 @@
 //  public static const int ACTCTX_FLAG_SET_PROCESS_DEFAULT = 0x00000010;
     public static const int ALTERNATE = 1;
     public static const int ASSOCF_NOTRUNCATE = 0x00000020;
+    public static const int ASSOCF_INIT_IGNOREUNKNOWN = 0x400;
     public static const int ASSOCSTR_COMMAND = 1;
     public static const int ASSOCSTR_DEFAULTICON = 15;
     public static const int ASSOCSTR_FRIENDLYAPPNAME = 4;
@@ -461,6 +462,12 @@
     public static const int AW_HOR_NEGATIVE = 0x00000002;
     public static const int AW_VER_POSITIVE = 0x00000004;
     public static const int AW_VER_NEGATIVE = 0x00000008;
+    public static const int ATTR_INPUT = 0x00;
+    public static const int ATTR_TARGET_CONVERTED = 0x01;
+    public static const int ATTR_CONVERTED = 0x02;
+    public static const int ATTR_TARGET_NOTCONVERTED = 0x03;
+    public static const int ATTR_INPUT_ERROR = 0x04;
+    public static const int ATTR_FIXEDCONVERTED = 0x05;
     public static const int BCM_FIRST = 0x1600;
     public static const int BCM_GETIDEALSIZE = BCM_FIRST + 0x1;
     public static const int BCM_GETIMAGELIST = BCM_FIRST + 0x3;
@@ -518,7 +525,9 @@
     public static const int BP_CHECKBOX = 3;
     public static const int BP_GROUPBOX = 4;
     public static const int BST_CHECKED = 0x1;
+    public static const int BST_INDETERMINATE = 0x2;
     public static const int BST_UNCHECKED = 0x0;
+    public static const int BS_3STATE = 0x5;
     public static const int BS_BITMAP = 0x80;
     public static const int BS_CENTER = 0x300;
     public static const int BS_CHECKBOX = 0x2;
@@ -594,6 +603,7 @@
     public static const int CBXS_HOT = 2;
     public static const int CBXS_PRESSED = 3;
     public static const int CBXS_DISABLED = 4;
+    public static const int CCHILDREN_SCROLLBAR = 5;
     public static const int CCM_FIRST = 0x2000;
     public static const int CCM_SETBKCOLOR = 0x2001;
     public static const int CCM_SETVERSION = 0x2007;
@@ -651,6 +661,8 @@
     public static const int CFM_WEIGHT = 0x400000;
     public static const int CFS_POINT = 0x2;
     public static const int CFS_RECT = 0x1;
+    public static const int CFS_CANDIDATEPOS = 0x0040;
+    public static const int CFS_EXCLUDE = 0x0080;
     public static const int CF_EFFECTS = 0x100;
     public static const int CF_INITTOLOGFONTSTRUCT = 0x40;
     public static const int CF_SCREENFONTS = 0x1;
@@ -695,6 +707,7 @@
     public static const int CP_UTF8 = 65001;
     public static const int CP_DROPDOWNBUTTON = 1;
     public static const int CP_INSTALLED = 0x1;
+    public static const int CPS_COMPLETE = 0x1;
     public static const int CS_BYTEALIGNWINDOW = 0x2000;
     public static const int CS_DBLCLKS = 0x8;
     public static const int CS_DROPSHADOW = 0x20000;
@@ -709,6 +722,8 @@
     public static const int DCX_CACHE = 0x2;
     public static const int DCX_CLIPCHILDREN = 0x8;
     public static const int DCX_CLIPSIBLINGS = 0x10;
+    public static const int DCX_INTERSECTRGN = 0x80;
+    public static const int DCX_WINDOW = 0x1;
     public static const int DEFAULT_CHARSET = 0x1;
     public static const int DEFAULT_GUI_FONT = 0x11;
     public static const int DFCS_BUTTONCHECK = 0x0;
@@ -759,11 +774,16 @@
     public static const int DTM_SETSYSTEMTIME = DTM_FIRST + 2;
     public static const int DTN_FIRST = 0xFFFFFD08;
     public static const int DTN_DATETIMECHANGE = DTN_FIRST + 1;
+    public static const int DTN_CLOSEUP = DTN_FIRST + 7;
+    public static const int DTN_DROPDOWN = DTN_FIRST + 6;
     public static const int DTS_LONGDATEFORMAT = 0x0004;
     public static const int DTS_SHORTDATECENTURYFORMAT = 0x000C;
     public static const int DTS_SHORTDATEFORMAT = 0x0000;
     public static const int DTS_TIMEFORMAT = 0x0009;
     public static const int DTS_UPDOWN = 0x0001;
+    public static const int DWM_BB_ENABLE = 0x1;
+    public static const int DWM_BB_BLURREGION = 0x2;
+    public static const int DWM_BB_TRANSITIONONMAXIMIZED = 0x4;
     public static const int E_POINTER = 0x80004003;
     public static const int EBP_NORMALGROUPBACKGROUND = 5;
     public static const int EBP_NORMALGROUPCOLLAPSE = 6;
@@ -856,6 +876,9 @@
     public static const int GBS_DISABLED = 2;
     public static const int GCS_COMPSTR = 0x8;
     public static const int GCS_RESULTSTR = 0x800;
+    public static const int GCS_COMPATTR = 0x0010;
+    public static const int GCS_COMPCLAUSE = 0x0020;
+    public static const int GCS_CURSORPOS = 0x0080;
     public static const int GDT_VALID = 0;
     public static const int GET_FEATURE_FROM_PROCESS = 0x2;
     public static const int GLPS_CLOSED = 1;
@@ -1026,6 +1049,7 @@
     public static const int IME_CMODE_KATAKANA = 0x2;
     public static const int IME_CMODE_NATIVE = 0x1;
     public static const int IME_CMODE_ROMAN = 0x10;
+    public static const int IMEMOUSE_LDOWN = 1;
     public static const int INFINITE = 0xffffffff;
     public static const int INPUT_KEYBOARD = 1;
     public static const int INPUT_MOUSE = 0;
@@ -1069,6 +1093,7 @@
     public static const int LB_RESETCONTENT = 0x184;
     public static const int LB_SELITEMRANGE = 0x19b;
     public static const int LB_SELITEMRANGEEX = 0x183;
+    public static const int LB_SETANCHORINDEX = 0xf19c;
     public static const int LB_SETCARETINDEX = 0x19e;
     public static const int LB_SETCURSEL = 0x186;
     public static const int LB_SETHORIZONTALEXTENT = 0x194;
@@ -1201,6 +1226,8 @@
     public static const int LVM_SETSELECTEDCOLUMN = LVM_FIRST + 140;
     public static const int LVM_SETTEXTBKCOLOR = 0x1026;
     public static const int LVM_SETTEXTCOLOR = 0x1024;
+    public static const int LVM_SETTOOLTIPS = LVM_FIRST + 74;
+    public static const int LVM_SUBITEMHITTEST = LVM_FIRST + 57;
     public static const int LVNI_FOCUSED = 0x1;
     public static const int LVNI_SELECTED = 0x2;
     public static const int LVN_BEGINDRAG = 0xffffff93;
@@ -1268,6 +1295,7 @@
     public static const int MCM_SETCURSEL = MCM_FIRST + 2;
     public static const int MCN_FIRST = 0xFFFFFD12;
     public static const int MCN_SELCHANGE = MCN_FIRST + 1;
+    public static const int MCN_SELECT = MCN_FIRST + 4;
     public static const int MCM_GETMINREQRECT = MCM_FIRST + 9;
     public static const int MCS_NOTODAY = 0x0010;
     public static const int MDIS_ALLCHILDSTYLES = 0x0001;
@@ -1294,6 +1322,7 @@
     public static const int MIIM_DATA = 0x20;
     public static const int MIIM_ID = 0x2;
     public static const int MIIM_STATE = 0x1;
+    public static const int MIIM_STRING = 0x40;
     public static const int MIIM_SUBMENU = 0x4;
     public static const int MIIM_TYPE = 0x10;
     public static const int MIM_BACKGROUND = 0x2;
@@ -1338,6 +1367,7 @@
     public static const int MSGF_SIZE = 4;
     public static const int MSGF_USER = 4096;
     public static const int MWMO_INPUTAVAILABLE = 0x4;
+    public static const int NI_COMPOSITIONSTR = 0x15;
     public static const int NIF_ICON = 0x00000002;
     public static const int NIF_INFO = 0x00000010;
     public static const int NIF_MESSAGE = 0x00000001;
@@ -1380,6 +1410,8 @@
     public static const int OBJ_BITMAP = 0x7;
     public static const int OBJ_FONT = 0x6;
     public static const int OBJ_PEN = 0x1;
+    public static const int OBJID_HSCROLL = 0xFFFFFFFA;
+    public static const int OBJID_VSCROLL = 0xFFFFFFFB;
     public static const TCHAR* OBM_CHECKBOXES = cast(TCHAR*)0x7ff7;
     public static const int ODS_SELECTED = 0x1;
     public static const int ODT_MENU = 0x1;
@@ -1388,6 +1420,7 @@
     public static const int OFN_ENABLEHOOK = 0x20;
     public static const int OFN_HIDEREADONLY = 0x4;
     public static const int OFN_NOCHANGEDIR = 0x8;
+    public static const int OFN_OVERWRITEPROMPT = 0x2;
     public static const int OIC_BANG = 0x7F03;
     public static const int OIC_HAND = 0x7F01;
     public static const int OIC_INFORMATION = 0x7F04;
@@ -1610,6 +1643,7 @@
     public static const int SM_CXDOUBLECLK = 36;
     public static const int SM_CYDOUBLECLK = 37;
     public static const int SM_CXEDGE = 0x2d;
+    public static const int SM_CXFOCUSBORDER = 83;
     public static const int SM_CXHSCROLL = 0x15;
     public static const int SM_CXICON = 0x0b;
     public static const int SM_CYICON = 0x0c;
@@ -1623,6 +1657,7 @@
     public static const int SM_CXVSCROLL = 0x2;
     public static const int SM_CYBORDER = 0x6;
     public static const int SM_CYCURSOR = 0xe;
+    public static const int SM_CYFOCUSBORDER = 84;
     public static const int SM_CYHSCROLL = 0x3;
     public static const int SM_CYMENU = 0xf;
     public static const int SM_CXMINTRACK = 34;
@@ -1635,8 +1670,10 @@
     public static const int SPI_GETFONTSMOOTHINGTYPE = 0x200A;
     public static const int SPI_GETHIGHCONTRAST = 66;
     public static const int SPI_GETWORKAREA = 0x30;
+    public static const int SPI_GETMOUSEVANISH = 0x1020;
     public static const int SPI_GETNONCLIENTMETRICS = 41;
     public static const int SPI_GETWHEELSCROLLLINES = 104;
+    public static const int SPI_GETCARETWIDTH = 0x2006;
     public static const int SPI_SETSIPINFO = 224;
     public static const int SPI_SETHIGHCONTRAST = 67;
     public static const int SRCAND = 0x8800c6;
@@ -1656,6 +1693,9 @@
     public static const int SS_RIGHT = 0x2;
     public static const int STANDARD_RIGHTS_READ = 0x20000;
     public static const int STARTF_USESHOWWINDOW = 0x1;
+    public static const int STATE_SYSTEM_INVISIBLE = 0x00008000;
+    public static const int STATE_SYSTEM_OFFSCREEN = 0x00010000;
+    public static const int STATE_SYSTEM_UNAVAILABLE = 0x00000001;
     public static const int STD_COPY = 0x1;
     public static const int STD_CUT = 0x0;
     public static const int STD_FILENEW = 0x6;
@@ -1787,6 +1827,7 @@
     public static const int TCM_GETITEMCOUNT = 0x1304;
     public static const int TCM_GETITEMRECT = 0x130a;
     public static const int TCM_GETTOOLTIPS = 0x132d;
+    public static const int TCM_HITTEST = 0x130d;
     public static const int TCM_INSERTITEM = IsUnicode ? 0x133e : 0x1307;
     public static const int TCM_SETCURSEL = 0x130c;
     public static const int TCM_SETIMAGELIST = 0x1303;
@@ -1799,6 +1840,21 @@
     public static const int TCS_TABS = 0x0;
     public static const int TCS_TOOLTIPS = 0x4000;
     public static const int TECHNOLOGY = 0x2;
+    public static const int TF_ATTR_INPUT = 0;
+    public static const int TF_ATTR_TARGET_CONVERTED = 1;
+    public static const int TF_ATTR_CONVERTED = 2;
+    public static const int TF_ATTR_TARGET_NOTCONVERTED = 3;
+    public static const int TF_ATTR_INPUT_ERROR = 4;
+    public static const int TF_ATTR_FIXEDCONVERTED = 5;
+    public static const int TF_ATTR_OTHER = -1;
+    public alias TF_DA_COLORTYPE.TF_CT_NONE TF_CT_NONE;
+    public alias TF_DA_COLORTYPE.TF_CT_SYSCOLOR TF_CT_SYSCOLOR;
+    public alias TF_DA_COLORTYPE.TF_CT_COLORREF TF_CT_COLORREF;
+    public alias TF_DA_LINESTYLE.TF_LS_NONE     TF_LS_NONE;
+    public alias TF_DA_LINESTYLE.TF_LS_SOLID    TF_LS_SOLID;
+    public alias TF_DA_LINESTYLE.TF_LS_DOT      TF_LS_DOT;
+    public alias TF_DA_LINESTYLE.TF_LS_DASH     TF_LS_DASH;
+    public alias TF_DA_LINESTYLE.TF_LS_SQUIGGLE TF_LS_SQUIGGLE;
     public static const int TIME_NOSECONDS = 0x2;
     public static const int TIS_NORMAL = 1;
     public static const int TIS_HOT = 2;
@@ -1864,6 +1920,7 @@
     public static const int TTI_ERROR= 3;
     public static const int TTM_ACTIVATE = 0x400 + 1;
     public static const int TTM_ADDTOOL = IsUnicode ? 0x432 : 0x404;
+    public static const int TTM_ADJUSTRECT = 0x400 + 31;
     public static const int TTM_GETCURRENTTOOLA = 0x400 + 15;
     public static const int TTM_GETCURRENTTOOLW = 0x400 + 59;
     public static const int TTM_GETCURRENTTOOL = 0x400 + (IsUnicode ? 59 : 15);
@@ -1888,6 +1945,9 @@
     public static const int TTN_SHOW = TTN_FIRST - 1;
     public static const int TTS_ALWAYSTIP = 0x1;
     public static const int TTS_BALLOON = 0x40;
+    public static const int TTS_NOANIMATE = 0x10;
+    public static const int TTS_NOFADE = 0x20;
+    public static const int TTS_NOPREFIX = 0x02;
     public static const int TV_FIRST = 0x1100;
     public static const int TVE_COLLAPSE = 0x1;
     public static const int TVE_COLLAPSERESET = 0x8000;
@@ -1906,6 +1966,8 @@
     public static const int TVHT_ONITEM = 0x46;
     public static const int TVHT_ONITEMBUTTON = 16;
     public static const int TVHT_ONITEMICON = 0x2;
+    public static const int TVHT_ONITEMINDENT = 0x8;
+    public static const int TVHT_ONITEMRIGHT = 0x20;
     public static const int TVHT_ONITEMLABEL = 0x4;
     public static const int TVHT_ONITEMSTATEICON = 0x40;
     public static const int TVIF_HANDLE = 0x10;
@@ -1919,10 +1981,10 @@
     public static const int TVIS_EXPANDED = 0x20;
     public static const int TVIS_SELECTED = 0x2;
     public static const int TVIS_STATEIMAGEMASK = 0xf000;
-    public static const int TVI_FIRST = 0xffff0001;
-    public static const int TVI_LAST = 0xffff0002;
-    public static const int TVI_ROOT = 0xffff0000;
-    public static const int TVI_SORT = 0xFFFF0003;
+    public static const int /*long*/ TVI_FIRST = -0x0FFFF;
+    public static const int /*long*/ TVI_LAST = -0x0FFFE;
+    public static const int /*long*/ TVI_ROOT = -0x10000;
+    public static const int /*long*/ TVI_SORT = -0x0FFFD;
     public static const int TVM_CREATEDRAGIMAGE = TV_FIRST + 18;
     public static const int TVM_DELETEITEM = 0x1101;
     public static const int TVM_ENSUREVISIBLE = 0x1114;
@@ -1992,6 +2054,7 @@
     public static const int TVS_LINESATROOT = 0x4;
     public static const int TVS_NOHSCROLL = 0x8000;
     public static const int TVS_NONEVENHEIGHT = 0x4000;
+    public static const int TVS_NOSCROLL = 0x2000;
     public static const int TVS_NOTOOLTIPS = 0x80;
     public static const int TVS_SHOWSELALWAYS = 0x20;
     public static const int TVS_TRACKSELECT = 0x200;
@@ -2008,7 +2071,9 @@
     public static const int UDS_ALIGNRIGHT = 0x004;
     public static const int UDS_AUTOBUDDY = 0x0010;
     public static const int UDS_WRAP = 0x0001;
+    public static const int UIS_CLEAR = 2;
     public static const int UIS_INITIALIZE = 3;
+    public static const int UIS_SET = 1;
     public static const int UISF_HIDEACCEL = 0x2;
     public static const int UISF_HIDEFOCUS = 0x1;
     public static const TCHAR[] UPDOWN_CLASS = "msctls_updown32"; //$NON-NLS-1$
@@ -2047,7 +2112,6 @@
     public static const int VK_MENU = 0x12;
     public static const int VK_MULTIPLY = 0x6A;
     public static const int VK_N = 0x4e;
-    public static const int VK_O = 0x4f;
     public static const int VK_NEXT = 0x22;
     public static const int VK_NUMLOCK = 0x90;
     public static const int VK_NUMPAD0 = 0x60;
@@ -2098,6 +2162,7 @@
     public static const int WM_ACTIVATE = 0x6;
     public static const int WM_ACTIVATEAPP = 0x1c;
     public static const int WM_APP = 0x8000;
+    public static const int WM_DWMCOLORIZATIONCOLORCHANGED = 0x320;
     public static const int WM_CANCELMODE = 0x1f;
     public static const int WM_CAPTURECHANGED = 0x0215;
     public static const int WM_CHANGEUISTATE = 0x0127;
@@ -2132,6 +2197,8 @@
     public static const int WM_HSCROLL = 0x114;
     public static const int WM_IME_CHAR = 0x286;
     public static const int WM_IME_COMPOSITION = 0x10f;
+    public static const int WM_IME_COMPOSITION_START = 0x010D;
+    public static const int WM_IME_ENDCOMPOSITION = 0x010E;
     public static const int WM_INITDIALOG = 0x110;
     public static const int WM_INITMENUPOPUP = 0x117;
     public static const int WM_INPUTLANGCHANGE = 0x51;
@@ -2206,8 +2273,10 @@
     public static const int WS_CLIPCHILDREN = 0x2000000;
     public static const int WS_CLIPSIBLINGS = 0x4000000;
     public static const int WS_DISABLED = 0x4000000;
+    public static const int WS_EX_APPWINDOW = 0x40000;
     public static const int WS_EX_CAPTIONOKBTN = 0x80000000;
     public static const int WS_EX_CLIENTEDGE = 0x200;
+    public static const int WS_EX_COMPOSITED = 0x2000000;
     public static const int WS_EX_DLGMODALFRAME = 0x1;
     public static const int WS_EX_LAYERED = 0x00080000;
     public static const int WS_EX_LAYOUTRTL = 0x00400000;
@@ -2243,7 +2312,7 @@
 /++
 /** Ansi/Unicode wrappers */
 
-public static final int /*long*/ AddFontResourceEx (TCHAR lpszFilename, int fl, int /*long*/ pdv) {
+public static const int /*long*/ AddFontResourceEx (TCHAR lpszFilename, int fl, int /*long*/ pdv) {
     if (IsUnicode) {
         char [] lpszFilename1 = lpszFilename is null ? null : lpszFilename.chars;
         return AddFontResourceExW (lpszFilename1, fl, pdv);
@@ -2252,7 +2321,7 @@
     return AddFontResourceExA (lpszFilename1, fl, pdv);
 }
 
-public static final int /*long*/ AssocQueryString(int flags, int str, TCHAR pszAssoc, TCHAR pszExtra, TCHAR pszOut, int[] pcchOut) {
+public static const int /*long*/ AssocQueryString(int flags, int str, TCHAR pszAssoc, TCHAR pszExtra, TCHAR pszOut, int[] pcchOut) {
     if (IsUnicode) {
         char [] pszAssoc1 = pszAssoc is null ? null : pszAssoc.chars;
         char [] pszExtra1 = pszExtra is null ? null : pszExtra.chars;
@@ -2265,7 +2334,7 @@
     return AssocQueryStringA (flags, str, pszAssoc1, pszExtra1, pszOut1, pcchOut);
 }
 
-public static final int /*long*/ CallWindowProc (int /*long*/ lpPrevWndFunc, int /*long*/ hWnd, int Msg, int /*long*/ wParam, int /*long*/ lParam) {
+public static const int /*long*/ CallWindowProc (int /*long*/ lpPrevWndFunc, int /*long*/ hWnd, int Msg, int /*long*/ wParam, int /*long*/ lParam) {
     if (IsUnicode) return CallWindowProcW (lpPrevWndFunc, hWnd, Msg, wParam, lParam);
     return CallWindowProcA (lpPrevWndFunc, hWnd, Msg, wParam, lParam);
 }
@@ -2290,17 +2359,17 @@
     return ChooseFontA (chooseFont);
 }
 
-public static final int /*long*/ CreateActCtx (ACTCTX pActCtx) {
+public static const int /*long*/ CreateActCtx (ACTCTX pActCtx) {
     if (IsUnicode) return CreateActCtxW (pActCtx);
     return CreateActCtxA (pActCtx);
 }
 
-public static final int /*long*/ CreateAcceleratorTable (byte [] lpaccl, int cEntries) {
+public static const int /*long*/ CreateAcceleratorTable (byte [] lpaccl, int cEntries) {
     if (IsUnicode) return CreateAcceleratorTableW (lpaccl, cEntries);
     return CreateAcceleratorTableA (lpaccl, cEntries);
 }
 
-public static final int /*long*/ CreateDC (TCHAR lpszDriver, TCHAR lpszDevice, int /*long*/ lpszOutput, int /*long*/ lpInitData) {
+public static const int /*long*/ CreateDC (TCHAR lpszDriver, TCHAR lpszDevice, int /*long*/ lpszOutput, int /*long*/ lpInitData) {
     if (IsUnicode) {
         char [] lpszDriver1 = lpszDriver is null ? null : lpszDriver.chars;
         char [] lpszDevice1 = lpszDevice is null ? null : lpszDevice.chars;
@@ -2311,12 +2380,12 @@
     return CreateDCA (lpszDriver1, lpszDevice1, lpszOutput, lpInitData);
 }
 
-public static final int /*long*/ CreateFontIndirect (int /*long*/ lplf) {
+public static const int /*long*/ CreateFontIndirect (int /*long*/ lplf) {
     if (IsUnicode) return CreateFontIndirectW (lplf);
     return CreateFontIndirectA (lplf);
 }
 
-public static final int /*long*/ CreateFontIndirect (LOGFONT lplf) {
+public static const int /*long*/ CreateFontIndirect (LOGFONT lplf) {
     if (IsUnicode) return CreateFontIndirectW ((LOGFONTW)lplf);
     return CreateFontIndirectA ((LOGFONTA)lplf);
 }
@@ -2326,7 +2395,7 @@
     return CreateProcessA (lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation);
 }
 
-public static final int /*long*/ CreateWindowEx (int dwExStyle, TCHAR lpClassName, TCHAR lpWindowName, int dwStyle, int X, int Y, int nWidth, int nHeight, int /*long*/ hWndParent, int /*long*/ hMenu, int /*long*/ hInstance, CREATESTRUCT lpParam) {
+public static const int /*long*/ CreateWindowEx (int dwExStyle, TCHAR lpClassName, TCHAR lpWindowName, int dwStyle, int X, int Y, int nWidth, int nHeight, int /*long*/ hWndParent, int /*long*/ hMenu, int /*long*/ hInstance, CREATESTRUCT lpParam) {
     if (IsUnicode) {
         char [] lpClassName1 = lpClassName is null ? null : lpClassName.chars;
         char [] lpWindowName1 = lpWindowName is null ? null : lpWindowName.chars;
@@ -2337,26 +2406,26 @@
     return CreateWindowExA (dwExStyle, lpClassName1, lpWindowName1, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
 }
 
-public static final int /*long*/ DefMDIChildProc (int /*long*/ hWnd, int Msg, int /*long*/ wParam, int /*long*/ lParam) {
+public static const int /*long*/ DefMDIChildProc (int /*long*/ hWnd, int Msg, int /*long*/ wParam, int /*long*/ lParam) {
     if (IsUnicode) return DefMDIChildProcW (hWnd, Msg, wParam, lParam);
     return DefMDIChildProcA (hWnd, Msg, wParam, lParam);
 }
 
-public static final int /*long*/ DefFrameProc (int /*long*/ hWnd, int /*long*/ hWndMDIClient, int Msg, int /*long*/ wParam, int /*long*/ lParam) {
+public static const int /*long*/ DefFrameProc (int /*long*/ hWnd, int /*long*/ hWndMDIClient, int Msg, int /*long*/ wParam, int /*long*/ lParam) {
     if (IsUnicode) return DefFrameProcW (hWnd, hWndMDIClient, Msg, wParam, lParam);
     return DefFrameProcA (hWnd, hWndMDIClient, Msg, wParam, lParam);
 }
-public static final int /*long*/ DefWindowProc (int /*long*/ hWnd, int Msg, int /*long*/ wParam, int /*long*/ lParam) {
+public static const int /*long*/ DefWindowProc (int /*long*/ hWnd, int Msg, int /*long*/ wParam, int /*long*/ lParam) {
     if (IsUnicode) return DefWindowProcW (hWnd, Msg, wParam, lParam);
     return DefWindowProcA (hWnd, Msg, wParam, lParam);
 }
 
-public static final int /*long*/ DispatchMessage (MSG lpmsg) {
+public static const int /*long*/ DispatchMessage (MSG lpmsg) {
     if (IsUnicode) return DispatchMessageW (lpmsg);
     return DispatchMessageA (lpmsg);
 }
 
-public static final int DragQueryFile (int /*long*/ hDrop, int iFile, TCHAR lpszFile, int cch) {
+public static const int DragQueryFile (int /*long*/ hDrop, int iFile, TCHAR lpszFile, int cch) {
     if (IsUnicode) {
         char [] lpszFile1 = lpszFile is null ? null : lpszFile.chars;
         return DragQueryFileW (hDrop, iFile, lpszFile1, cch);
@@ -2370,7 +2439,7 @@
     return DrawStateA (hdc, hbr, lpOutputFunc, lData, wData, x, y, cx, cy, fuFlags);
 }
 
-public static final int DrawText (int /*long*/ hDC, TCHAR lpString, int nCount, RECT lpRect, int uFormat) {
+public static const int DrawText (int /*long*/ hDC, TCHAR lpString, int nCount, RECT lpRect, int uFormat) {
     if (IsUnicode) {
         char [] lpString1 = lpString is null ? null : lpString.chars;
         return DrawTextW (hDC, lpString1, nCount, lpRect, uFormat);
@@ -2379,7 +2448,7 @@
     return DrawTextA (hDC, lpString1, nCount, lpRect, uFormat);
 }
 
-public static final int EnumFontFamilies (int /*long*/ hdc, TCHAR lpszFamily, int /*long*/ lpEnumFontFamProc, int /*long*/ lParam) {
+public static const int EnumFontFamilies (int /*long*/ hdc, TCHAR lpszFamily, int /*long*/ lpEnumFontFamProc, int /*long*/ lParam) {
     if (IsUnicode) {
         char [] lpszFamily1 = lpszFamily is null ? null : lpszFamily.chars;
         return EnumFontFamiliesW (hdc, lpszFamily1, lpEnumFontFamProc, lParam);
@@ -2388,7 +2457,7 @@
     return EnumFontFamiliesA (hdc, lpszFamily1, lpEnumFontFamProc, lParam);
 }
 
-public static final int EnumFontFamiliesEx (int /*long*/ hdc, LOGFONT lpLogfont, int /*long*/ lpEnumFontFamExProc, int /*long*/ lParam, int dwFlags) {
+public static const int EnumFontFamiliesEx (int /*long*/ hdc, LOGFONT lpLogfont, int /*long*/ lpEnumFontFamExProc, int /*long*/ lParam, int dwFlags) {
     if (IsUnicode) return EnumFontFamiliesExW (hdc, (LOGFONTW)lpLogfont, lpEnumFontFamExProc, lParam, dwFlags);
     return EnumFontFamiliesExA (hdc, (LOGFONTA)lpLogfont, lpEnumFontFamExProc, lParam, dwFlags);
 }
@@ -2403,7 +2472,7 @@
     return EnumSystemLanguageGroupsA (pLangGroupEnumProc, dwFlags, lParam);
 }
 
-public static final int ExpandEnvironmentStrings (TCHAR lpSrc, TCHAR lpDst, int nSize) {
+public static const int ExpandEnvironmentStrings (TCHAR lpSrc, TCHAR lpDst, int nSize) {
     if (IsUnicode) {
         char [] lpSrc1 = lpSrc is null ? null : lpSrc.chars;
         char [] lpDst1 = lpDst is null ? null : lpDst.chars;
@@ -2414,7 +2483,7 @@
     return ExpandEnvironmentStringsA (lpSrc1, lpDst1, nSize);
 }
 
-public static final int ExtractIconEx (TCHAR lpszFile, int nIconIndex, int /*long*/ [] phiconLarge, int /*long*/ [] phiconSmall, int nIcons) {
+public static const int ExtractIconEx (TCHAR lpszFile, int nIconIndex, int /*long*/ [] phiconLarge, int /*long*/ [] phiconSmall, int nIcons) {
     if (IsUnicode) {
         char [] lpszFile1 = lpszFile is null ? null : lpszFile.chars;
         return ExtractIconExW (lpszFile1, nIconIndex, phiconLarge, phiconSmall, nIcons);
@@ -2432,7 +2501,7 @@
     return ExtTextOutA (hdc, X, Y, fuOptions, lprc, lpString1, cbCount, lpDx);
 }
 
-public static final int /*long*/ FindWindow (TCHAR lpClassName, TCHAR lpWindowName) {
+public static const int /*long*/ FindWindow (TCHAR lpClassName, TCHAR lpWindowName) {
     if (IsUnicode) {
         char [] lpClassName1 = lpClassName is null ? null : lpClassName.chars;
         char [] lpWindowName1 = lpWindowName is null ? null : lpWindowName.chars;
@@ -2443,7 +2512,7 @@
     return FindWindowA (lpClassName1, lpWindowName1);
 }
 
-public static final int FormatMessage (int dwFlags, int /*long*/ lpSource, int dwMessageId, int dwLanguageId, int[] lpBuffer, int nSize, int /*long*/ Arguments) {
+public static const int FormatMessage (int dwFlags, int /*long*/ lpSource, int dwMessageId, int dwLanguageId, int[] lpBuffer, int nSize, int /*long*/ Arguments) {
     if (IsUnicode) {
         return FormatMessageW (dwFlags, lpSource, dwMessageId, dwLanguageId, lpBuffer, nSize, Arguments);
     }
@@ -2455,7 +2524,7 @@
     return GetCharABCWidthsA (hdc,iFirstChar, iLastChar, lpabc);
 }
 
-public static final int GetCharacterPlacement (int /*long*/ hdc, TCHAR lpString, int nCount, int nMaxExtent, GCP_RESULTS lpResults, int dwFlags) {
+public static const int GetCharacterPlacement (int /*long*/ hdc, TCHAR lpString, int nCount, int nMaxExtent, GCP_RESULTS lpResults, int dwFlags) {
     if (IsUnicode) {
         char [] lpString1 = lpString is null ? null : lpString.chars;
         return GetCharacterPlacementW (hdc, lpString1, nCount, nMaxExtent, lpResults, dwFlags);
@@ -2478,7 +2547,7 @@
     return GetClassInfoA (hInstance, lpClassName1, lpWndClass);
 }
 
-public static final int GetClassName (int /*long*/ hWnd, TCHAR lpClassName, int nMaxCount) {
+public static const int GetClassName (int /*long*/ hWnd, TCHAR lpClassName, int nMaxCount) {
     if (IsUnicode) {
         char [] lpClassName1 = lpClassName is null ? null : lpClassName.chars;
         return GetClassNameW (hWnd, lpClassName1, nMaxCount);
@@ -2487,7 +2556,7 @@
     return GetClassNameA (hWnd, lpClassName1, nMaxCount);
 }
 
-public static final int GetClipboardFormatName (int format, TCHAR lpszFormatName, int cchMaxCount) {
+public static const int GetClipboardFormatName (int format, TCHAR lpszFormatName, int cchMaxCount) {
     if (IsUnicode) {
         char [] lpszFormatName1 = lpszFormatName is null ? null : lpszFormatName.chars;
         return GetClipboardFormatNameW (format, lpszFormatName1, cchMaxCount);
@@ -2496,7 +2565,7 @@
     return GetClipboardFormatNameA (format, lpszFormatName1, cchMaxCount);
 }
 
-public static final int GetDateFormat (int Locale, int dwFlags, SYSTEMTIME lpDate, TCHAR lpFormat, TCHAR lpDateStr, int cchDate) {
+public static const int GetDateFormat (int Locale, int dwFlags, SYSTEMTIME lpDate, TCHAR lpFormat, TCHAR lpDateStr, int cchDate) {
     if (IsUnicode) {
         char [] lpString1 = lpFormat is null ? null : lpFormat.chars;
         char [] lpString2 = lpDateStr is null ? null : lpDateStr.chars;
@@ -2507,7 +2576,7 @@
     return GetDateFormatA (Locale, dwFlags, lpDate, lpString1, lpString2, cchDate);
 }
 
-public static final int GetKeyNameText (int lParam, TCHAR lpString, int nSize) {
+public static const int GetKeyNameText (int lParam, TCHAR lpString, int nSize) {
     if (IsUnicode) {
         char [] lpString1 = lpString is null ? null : lpString.chars;
         return GetKeyNameTextW (lParam, lpString1, nSize);
@@ -2516,7 +2585,7 @@
     return GetKeyNameTextA (lParam, lpString1, nSize);
 }
 
-public static final int GetLocaleInfo (int Locale, int LCType, TCHAR lpLCData, int cchData) {
+public static const int GetLocaleInfo (int Locale, int LCType, TCHAR lpLCData, int cchData) {
     if (IsUnicode) {
         char [] lpLCData1 = lpLCData is null ? null : lpLCData.chars;
         return GetLocaleInfoW (Locale, LCType, lpLCData1, cchData);
@@ -2535,7 +2604,7 @@
     return GetMessageA (lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax);
 }
 
-public static final int GetModuleFileName (int /*long*/ hModule, TCHAR lpFilename, int inSize) {
+public static const int GetModuleFileName (int /*long*/ hModule, TCHAR lpFilename, int inSize) {
     if (IsUnicode) {
         char [] lpFilename1 = lpFilename is null ? null : lpFilename.chars;
         return GetModuleFileNameW (hModule, lpFilename1, inSize);
@@ -2544,7 +2613,7 @@
     return GetModuleFileNameA (hModule, lpFilename1, inSize);
 }
 
-public static final int /*long*/ GetModuleHandle (TCHAR lpModuleName) {
+public static const int /*long*/ GetModuleHandle (TCHAR lpModuleName) {
     if (IsUnicode) {
         char [] lpModuleName1 = lpModuleName is null ? null : lpModuleName.chars;
         return GetModuleHandleW (lpModuleName1);
@@ -2558,37 +2627,37 @@
     return GetMonitorInfoA (hmonitor, lpmi);
 }
 
-public static final int GetObject (int /*long*/ hgdiobj, int cbBuffer, BITMAP lpvObject) {
+public static const int GetObject (int /*long*/ hgdiobj, int cbBuffer, BITMAP lpvObject) {
     if (IsUnicode) return GetObjectW (hgdiobj, cbBuffer, lpvObject);
     return GetObjectA (hgdiobj, cbBuffer, lpvObject);
 }
 
-public static final int GetObject (int /*long*/ hgdiobj, int cbBuffer, DIBSECTION lpvObject) {
+public static const int GetObject (int /*long*/ hgdiobj, int cbBuffer, DIBSECTION lpvObject) {
     if (IsUnicode) return GetObjectW (hgdiobj, cbBuffer, lpvObject);
     return GetObjectA (hgdiobj, cbBuffer, lpvObject);
 }
 
-public static final int GetObject (int /*long*/ hgdiobj, int cbBuffer, EXTLOGPEN lpvObject) {
+public static const int GetObject (int /*long*/ hgdiobj, int cbBuffer, EXTLOGPEN lpvObject) {
     if (IsUnicode) return GetObjectW (hgdiobj, cbBuffer, lpvObject);
     return GetObjectA (hgdiobj, cbBuffer, lpvObject);
 }
 
-public static final int GetObject (int /*long*/ hgdiobj, int cbBuffer, LOGBRUSH lpvObject) {
+public static const int GetObject (int /*long*/ hgdiobj, int cbBuffer, LOGBRUSH lpvObject) {
     if (IsUnicode) return GetObjectW (hgdiobj, cbBuffer, lpvObject);
     return GetObjectA (hgdiobj, cbBuffer, lpvObject);
 }
 
-public static final int GetObject (int /*long*/ hgdiobj, int cbBuffer, LOGFONT lpvObject) {
+public static const int GetObject (int /*long*/ hgdiobj, int cbBuffer, LOGFONT lpvObject) {
     if (IsUnicode) return GetObjectW (hgdiobj, cbBuffer, (LOGFONTW)lpvObject);
     return GetObjectA (hgdiobj, cbBuffer, (LOGFONTA)lpvObject);
 }
 
-public static final int GetObject (int /*long*/ hgdiobj, int cbBuffer, LOGPEN lpvObject) {
+public static const int GetObject (int /*long*/ hgdiobj, int cbBuffer, LOGPEN lpvObject) {
     if (IsUnicode) return GetObjectW (hgdiobj, cbBuffer, lpvObject);
     return GetObjectA (hgdiobj, cbBuffer, lpvObject);
 }
 
-public static final int GetObject (int /*long*/ hgdiobj, int cbBuffer, int /*long*/ lpvObject) {
+public static const int GetObject (int /*long*/ hgdiobj, int cbBuffer, int /*long*/ lpvObject) {
     if (IsUnicode) return GetObjectW (hgdiobj, cbBuffer, lpvObject);
     return GetObjectA (hgdiobj, cbBuffer, lpvObject);
 }
@@ -2598,7 +2667,7 @@
     return GetOpenFileNameA (lpofn);
 }
 
-public static final int GetProfileString (TCHAR lpAppName, TCHAR lpKeyName, TCHAR lpDefault, TCHAR lpReturnedString, int nSize) {
+public static const int GetProfileString (TCHAR lpAppName, TCHAR lpKeyName, TCHAR lpDefault, TCHAR lpReturnedString, int nSize) {
     if (IsUnicode) {
         char [] lpAppName1 = lpAppName is null ? null : lpAppName.chars;
         char [] lpKeyName1 = lpKeyName is null ? null : lpKeyName.chars;
@@ -2645,7 +2714,7 @@
     return GetTextMetricsA (hdc, (TEXTMETRICA)lptm);
 }
 
-public static final int GetTimeFormat (int Locale, int dwFlags, SYSTEMTIME lpTime, TCHAR lpFormat, TCHAR lpTimeStr, int cchTime) {
+public static const int GetTimeFormat (int Locale, int dwFlags, SYSTEMTIME lpTime, TCHAR lpFormat, TCHAR lpTimeStr, int cchTime) {
     if (IsUnicode) {
         char [] lpString1 = lpFormat is null ? null : lpFormat.chars;
         char [] lpString2 = lpTimeStr is null ? null : lpTimeStr.chars;
@@ -2666,17 +2735,17 @@
     return GetVersionExA ((OSVERSIONINFOEXA)lpVersionInfo);
 }
 
-public static final int GetWindowLong (int /*long*/ hWnd, int nIndex) {
+public static const int GetWindowLong (int /*long*/ hWnd, int nIndex) {
     if (IsUnicode) return GetWindowLongW (hWnd, nIndex);
     return GetWindowLongA (hWnd, nIndex);
 }
 
-public static final int /*long*/ GetWindowLongPtr (int /*long*/ hWnd, int nIndex) {
+public static const int /*long*/ GetWindowLongPtr (int /*long*/ hWnd, int nIndex) {
     if (IsUnicode) return GetWindowLongPtrW (hWnd, nIndex);
     return GetWindowLongPtrA (hWnd, nIndex);
 }
 
-public static final int GetWindowText (int /*long*/ hWnd, TCHAR lpString, int nMaxCount) {
+public static const int GetWindowText (int /*long*/ hWnd, TCHAR lpString, int nMaxCount) {
     if (IsUnicode) {
         char [] lpString1 = lpString is null ? null : lpString.chars;
         return GetWindowTextW (hWnd, lpString1, nMaxCount);
@@ -2685,12 +2754,12 @@
     return GetWindowTextA (hWnd, lpString1, nMaxCount);
 }
 
-public static final int GetWindowTextLength (int /*long*/ hWnd) {
+public static const int GetWindowTextLength (int /*long*/ hWnd) {
     if (IsUnicode) return GetWindowTextLengthW (hWnd);
     return GetWindowTextLengthA (hWnd);
 }
 
-public static final int GlobalAddAtom (TCHAR lpString) {
+public static const int GlobalAddAtom (TCHAR lpString) {
     if (IsUnicode) {
         char [] lpString1 = lpString is null ? null : lpString.chars;
         return GlobalAddAtomW (lpString1);
@@ -2709,7 +2778,7 @@
     return ImmSetCompositionFontA (hIMC, (LOGFONTA)lplf);
 }
 
-public static final int ImmGetCompositionString (int /*long*/ hIMC, int dwIndex, TCHAR lpBuf, int dwBufLen) {
+public static const int ImmGetCompositionString (int /*long*/ hIMC, int dwIndex, TCHAR lpBuf, int dwBufLen) {
     if (IsUnicode) {
         char [] lpBuf1 = lpBuf is null ? null : lpBuf.chars;
         return ImmGetCompositionStringW (hIMC, dwIndex, lpBuf1, dwBufLen);
@@ -2732,22 +2801,22 @@
     return InsertMenuItemA (hMenu, uItem, fByPosition, lpmii);
 }
 
-public static final int /*long*/ LoadBitmap (int /*long*/ hInstance, int /*long*/ lpBitmapName) {
+public static const int /*long*/ LoadBitmap (int /*long*/ hInstance, int /*long*/ lpBitmapName) {
     if (IsUnicode) return LoadBitmapW (hInstance, lpBitmapName);
     return LoadBitmapA (hInstance, lpBitmapName);
 }
 
-public static final int /*long*/ LoadCursor (int /*long*/ hInstance, int /*long*/ lpCursorName) {
+public static const int /*long*/ LoadCursor (int /*long*/ hInstance, int /*long*/ lpCursorName) {
     if (IsUnicode) return LoadCursorW (hInstance, lpCursorName);
     return LoadCursorA (hInstance, lpCursorName);
 }
 
-public static final int /*long*/ LoadIcon (int /*long*/ hInstance, int /*long*/ lpIconName) {
+public static const int /*long*/ LoadIcon (int /*long*/ hInstance, int /*long*/ lpIconName) {
     if (IsUnicode) return LoadIconW (hInstance, lpIconName);
     return LoadIconA (hInstance, lpIconName);
 }
 
-public static final int /*long*/ LoadImage (int /*long*/ hinst, TCHAR lpszName, int uType, int cxDesired, int cyDesired, int fuLoad) {
+public static const int /*long*/ LoadImage (int /*long*/ hinst, TCHAR lpszName, int uType, int cxDesired, int cyDesired, int fuLoad) {
     if (IsUnicode) {
         char [] lpszName1 = lpszName is null ? null : lpszName.chars;
         return LoadImageW (hinst, lpszName1, uType, cxDesired, cyDesired, fuLoad);
@@ -2756,12 +2825,12 @@
     return LoadImageA (hinst, lpszName1, uType, cxDesired, cyDesired, fuLoad);
 }
 
-public static final int /*long*/ LoadImage (int /*long*/ hinst, int /*long*/ lpszName, int uType, int cxDesired, int cyDesired, int fuLoad) {
+public static const int /*long*/ LoadImage (int /*long*/ hinst, int /*long*/ lpszName, int uType, int cxDesired, int cyDesired, int fuLoad) {
     if (IsUnicode) return LoadImageW (hinst, lpszName, uType, cxDesired, cyDesired, fuLoad);
     return LoadImageA (hinst, lpszName, uType, cxDesired, cyDesired, fuLoad);
 }
 
-public static final int /*long*/ LoadLibrary (TCHAR lpLibFileName) {
+public static const int /*long*/ LoadLibrary (TCHAR lpLibFileName) {
     if (IsUnicode) {
         char [] lpLibFileName1 = lpLibFileName is null ? null : lpLibFileName.chars;
         return LoadLibraryW (lpLibFileName1);
@@ -2770,7 +2839,7 @@
     return LoadLibraryA (lpLibFileName1);
 }
 
-public static final int LoadString (int /*long*/ hinst, int uID, TCHAR lpBuffer, int nBufferMax) {
+public static const int LoadString (int /*long*/ hinst, int uID, TCHAR lpBuffer, int nBufferMax) {
     if (IsUnicode) {
         char [] lpBuffer1 = lpBuffer is null ? null : lpBuffer.chars;
         return LoadStringW (hinst, uID, lpBuffer1, nBufferMax);
@@ -2779,12 +2848,12 @@
     return LoadStringA (hinst, uID, lpBuffer1, nBufferMax);
 }
 
-public static final int MapVirtualKey (int uCode, int uMapType) {
+public static const int MapVirtualKey (int uCode, int uMapType) {
     if (IsUnicode) return MapVirtualKeyW (uCode, uMapType);
     return MapVirtualKeyA (uCode, uMapType);
 }
 
-public static final int MessageBox (int /*long*/ hWnd, TCHAR lpText, TCHAR lpCaption, int uType) {
+public static const int MessageBox (int /*long*/ hWnd, TCHAR lpText, TCHAR lpCaption, int uType) {
     if (IsUnicode) {
         char [] lpText1 = lpText is null ? null : lpText.chars;
         char [] lpCaption1 = lpCaption is null ? null : lpCaption.chars;
@@ -2875,7 +2944,7 @@
     return PrintDlgA (lppd);
 }
 
-public static final int RegEnumKeyEx (int /*long*/ hKey, int dwIndex, TCHAR lpName, int [] lpcName, int [] lpReserved, TCHAR lpClass, int [] lpcClass, FILETIME lpftLastWriteTime) {
+public static const int RegEnumKeyEx (int /*long*/ hKey, int dwIndex, TCHAR lpName, int [] lpcName, int [] lpReserved, TCHAR lpClass, int [] lpcClass, FILETIME lpftLastWriteTime) {
     if (IsUnicode) {
         char [] lpName1 = lpName is null ? null : lpName.chars;
         char [] lpClass1 = lpClass is null ? null : lpClass.chars;
@@ -2886,12 +2955,12 @@
     return RegEnumKeyExA (hKey, dwIndex, lpName1, lpcName, lpReserved, lpClass1, lpcClass, lpftLastWriteTime);
 }
 
-public static final int RegisterClass (WNDCLASS lpWndClass) {
+public static const int RegisterClass (WNDCLASS lpWndClass) {
     if (IsUnicode) return RegisterClassW (lpWndClass);
     return RegisterClassA (lpWndClass);
 }
 
-public static final int RegisterClipboardFormat (TCHAR lpszFormat) {
+public static const int RegisterClipboardFormat (TCHAR lpszFormat) {
     if (IsUnicode) {
         char [] lpszFormat1 = lpszFormat is null ? null : lpszFormat.chars;
         return RegisterClipboardFormatW (lpszFormat1);
@@ -2900,7 +2969,7 @@
     return RegisterClipboardFormatA (lpszFormat1);
 }
 
-public static final int RegisterWindowMessage (TCHAR lpString) {
+public static const int RegisterWindowMessage (TCHAR lpString) {
     if (IsUnicode) {
         char [] lpString1 = lpString is null ? null : lpString.chars;
         return RegisterWindowMessageW (lpString1);
@@ -2909,7 +2978,7 @@
     return RegisterWindowMessageA (lpString1);
 }
 
-public static final int RegOpenKeyEx (int /*long*/ hKey, TCHAR lpSubKey, int ulOptions, int samDesired, int /*long*/[] phkResult) {
+public static const int RegOpenKeyEx (int /*long*/ hKey, TCHAR lpSubKey, int ulOptions, int samDesired, int /*long*/[] phkResult) {
     if (IsUnicode) {
         char [] lpSubKey1 = lpSubKey is null ? null : lpSubKey.chars;
         return RegOpenKeyExW (hKey, lpSubKey1, ulOptions, samDesired, phkResult);
@@ -2918,12 +2987,12 @@
     return RegOpenKeyExA (hKey, lpSubKey1, ulOptions, samDesired, phkResult);
 }
 
-public static final int RegQueryInfoKey (int /*long*/ hKey, int /*long*/ lpClass, int[] lpcbClass, int /*long*/ lpReserved, int[] lpSubKeys, int[] lpcbMaxSubKeyLen, int[] lpcbMaxClassLen, int[] lpcValues, int[] lpcbMaxValueNameLen, int[] lpcbMaxValueLen, int[] lpcbSecurityDescriptor, int /*long*/ lpftLastWriteTime){
+public static const int RegQueryInfoKey (int /*long*/ hKey, int /*long*/ lpClass, int[] lpcbClass, int /*long*/ lpReserved, int[] lpSubKeys, int[] lpcbMaxSubKeyLen, int[] lpcbMaxClassLen, int[] lpcValues, int[] lpcbMaxValueNameLen, int[] lpcbMaxValueLen, int[] lpcbSecurityDescriptor, int /*long*/ lpftLastWriteTime){
     if (IsUnicode) return RegQueryInfoKeyW (hKey, lpClass, lpcbClass, lpReserved, lpSubKeys, lpcbMaxSubKeyLen, lpcbMaxClassLen, lpcValues, lpcbMaxValueNameLen, lpcbMaxValueLen, lpcbSecurityDescriptor, lpftLastWriteTime);
     return RegQueryInfoKeyA (hKey, lpClass, lpcbClass, lpReserved, lpSubKeys, lpcbMaxSubKeyLen, lpcbMaxClassLen, lpcValues, lpcbMaxValueNameLen, lpcbMaxValueLen, lpcbSecurityDescriptor, lpftLastWriteTime);
 }
 
-public static final int RegQueryValueEx (int /*long*/ hKey, TCHAR lpValueName, int /*long*/ lpReserved, int[] lpType, TCHAR lpData, int[] lpcbData) {
+public static const int RegQueryValueEx (int /*long*/ hKey, TCHAR lpValueName, int /*long*/ lpReserved, int[] lpType, TCHAR lpData, int[] lpcbData) {
     if (IsUnicode) {
         char [] lpValueName1 = lpValueName is null ? null : lpValueName.chars;
         char [] lpData1 = lpData is null ? null : lpData.chars;
@@ -2934,7 +3003,7 @@
     return RegQueryValueExA (hKey, lpValueName1, lpReserved, lpType, lpData1, lpcbData);
 }
 
-public static final int RegQueryValueEx (int /*long*/ hKey, TCHAR lpValueName, int /*long*/ lpReserved, int[] lpType, int [] lpData, int[] lpcbData) {
+public static const int RegQueryValueEx (int /*long*/ hKey, TCHAR lpValueName, int /*long*/ lpReserved, int[] lpType, int [] lpData, int[] lpcbData) {
     if (IsUnicode) {
         char [] lpValueName1 = lpValueName is null ? null : lpValueName.chars;
         return RegQueryValueExW (hKey, lpValueName1, lpReserved, lpType, lpData, lpcbData);
@@ -2943,12 +3012,12 @@
     return RegQueryValueExA (hKey, lpValueName1, lpReserved, lpType, lpData, lpcbData);
 }
 
-public static final int /*long*/ RemoveProp  (int /*long*/ hWnd, int /*long*/ lpString){
+public static const int /*long*/ RemoveProp  (int /*long*/ hWnd, int /*long*/ lpString){
     if (IsUnicode) return RemovePropW (hWnd, lpString);
     return RemovePropA (hWnd, lpString);
 }
 
-public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, TCHAR lParam) {
+public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, TCHAR lParam) {
     if (IsUnicode) {
         char [] lParam1 = lParam is null ? null : lParam.chars;
         return SendMessageW (hWnd, Msg, wParam, lParam1);
@@ -2957,147 +3026,147 @@
     return SendMessageA (hWnd, Msg, wParam, lParam1);
 }
 
-public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int [] wParam, int [] lParam) {
+public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int [] wParam, int [] lParam) {
     if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam);
     return SendMessageA (hWnd, Msg, wParam, lParam);
 }
 
-public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, SIZE lParam) {
+public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, SIZE lParam) {
     if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam);
     return SendMessageA (hWnd, Msg, wParam, lParam);
 }
 
-public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ [] wParam, int /*long*/ lParam) {
+public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ [] wParam, int /*long*/ lParam) {
     if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam);
     return SendMessageA (hWnd, Msg, wParam, lParam);
 }
 
-public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, int [] lParam) {
+public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, int [] lParam) {
     if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam);
     return SendMessageA (hWnd, Msg, wParam, lParam);
 }
 
-public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, char [] lParam) {
+public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, char [] lParam) {
     if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam);
     return SendMessageA (hWnd, Msg, wParam, lParam);
 }
 
-public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, short [] lParam) {
+public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, short [] lParam) {
     if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam);
     return SendMessageA (hWnd, Msg, wParam, lParam);
 }
 
-public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, int /*long*/ lParam) {
+public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, int /*long*/ lParam) {
     if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam);
     return SendMessageA (hWnd, Msg, wParam, lParam);
 }
 
-public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, LITEM lParam) {
+public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, LITEM lParam) {
     if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam);
     return SendMessageA (hWnd, Msg, wParam, lParam);
 }
 
-public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, LVCOLUMN lParam) {
+public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, LVCOLUMN lParam) {
     if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam);
     return SendMessageA (hWnd, Msg, wParam, lParam);
 }
 
-public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, LVHITTESTINFO lParam) {
+public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, LVHITTESTINFO lParam) {
     if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam);
     return SendMessageA (hWnd, Msg, wParam, lParam);
 }
 
-public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, LVITEM lParam) {
+public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, LVITEM lParam) {
     if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam);
     return SendMessageA (hWnd, Msg, wParam, lParam);
 }
 
-public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, MARGINS lParam) {
+public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, MARGINS lParam) {
     if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam);
     return SendMessageA (hWnd, Msg, wParam, lParam);
 }
 
-public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, POINT lParam) {
+public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, POINT lParam) {
     if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam);
     return SendMessageA (hWnd, Msg, wParam, lParam);
 }
 
-public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, REBARBANDINFO lParam) {
+public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, REBARBANDINFO lParam) {
     if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam);
     return SendMessageA (hWnd, Msg, wParam, lParam);
 }
 
-public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, RECT lParam) {
+public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, RECT lParam) {
     if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam);
     return SendMessageA (hWnd, Msg, wParam, lParam);
 }
 
-public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, SYSTEMTIME lParam) {
+public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, SYSTEMTIME lParam) {
     if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam);
     return SendMessageA (hWnd, Msg, wParam, lParam);
 }
 
-public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, TBBUTTON lParam) {
+public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, TBBUTTON lParam) {
     if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam);
     return SendMessageA (hWnd, Msg, wParam, lParam);
 }
 
-public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, TBBUTTONINFO lParam) {
+public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, TBBUTTONINFO lParam) {
     if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam);
     return SendMessageA (hWnd, Msg, wParam, lParam);
 }
 
-public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, TCITEM lParam) {
+public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, TCITEM lParam) {
     if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam);
     return SendMessageA (hWnd, Msg, wParam, lParam);
 }
 
-public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, TOOLINFO lParam) {
+public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, TOOLINFO lParam) {
     if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam);
     return SendMessageA (hWnd, Msg, wParam, lParam);
 }
 
-public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, TVHITTESTINFO lParam) {
+public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, TVHITTESTINFO lParam) {
     if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam);
     return SendMessageA (hWnd, Msg, wParam, lParam);
 }
 
-public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, TVINSERTSTRUCT lParam) {
+public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, TVINSERTSTRUCT lParam) {
     if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam);
     return SendMessageA (hWnd, Msg, wParam, lParam);
 }
 
-public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, TVITEM lParam) {
+public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, TVITEM lParam) {
     if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam);
     return SendMessageA (hWnd, Msg, wParam, lParam);
 }
 
-public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, TVSORTCB lParam) {
+public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, TVSORTCB lParam) {
     if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam);
     return SendMessageA (hWnd, Msg, wParam, lParam);
 }
 
-public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, UDACCEL lParam) {
+public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, UDACCEL lParam) {
     if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam);
     return SendMessageA (hWnd, Msg, wParam, lParam);
 }
 
-public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, HDHITTESTINFO lParam) {
+public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, HDHITTESTINFO lParam) {
     if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam);
     return SendMessageA (hWnd, Msg, wParam, lParam);
 }
 
-public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, HDITEM lParam) {
+public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, HDITEM lParam) {
     if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam);
     return SendMessageA (hWnd, Msg, wParam, lParam);
 }
 
-public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, HDLAYOUT lParam) {
+public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, HDLAYOUT lParam) {
     if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam);
     return SendMessageA (hWnd, Msg, wParam, lParam);
 }
 
-public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, BUTTON_IMAGELIST lParam) {
+public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, BUTTON_IMAGELIST lParam) {
     if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam);
     return SendMessageA (hWnd, Msg, wParam, lParam);
 }
@@ -3112,17 +3181,17 @@
     return SetPropA (hWnd, lpString, hData);
 }
 
-public static final int SetWindowLong (int /*long*/ hWnd, int nIndex, int dwNewLong) {
+public static const int SetWindowLong (int /*long*/ hWnd, int nIndex, int dwNewLong) {
     if (IsUnicode) return SetWindowLongW (hWnd, nIndex, dwNewLong);
     return SetWindowLongA (hWnd, nIndex, dwNewLong);
 }
 
-public static final int /*long*/ SetWindowLongPtr (int /*long*/ hWnd, int nIndex, int /*long*/ dwNewLong) {
+public static const int /*long*/ SetWindowLongPtr (int /*long*/ hWnd, int nIndex, int /*long*/ dwNewLong) {
     if (IsUnicode) return SetWindowLongPtrW (hWnd, nIndex, dwNewLong);
     return SetWindowLongPtrA (hWnd, nIndex, dwNewLong);
 }
 
-public static final int /*long*/ SetWindowsHookEx (int idHook, int /*long*/ lpfn, int /*long*/ hMod, int dwThreadId) {
+public static const int /*long*/ SetWindowsHookEx (int idHook, int /*long*/ lpfn, int /*long*/ hMod, int dwThreadId) {
     if (IsUnicode) return SetWindowsHookExW (idHook, lpfn, hMod, dwThreadId);
     return SetWindowsHookExA (idHook, lpfn, hMod, dwThreadId);
 }
@@ -3136,7 +3205,7 @@
     return SetWindowTextA (hWnd, lpString1);
 }
 
-public static final int /*long*/ SHBrowseForFolder (BROWSEINFO lpbi) {
+public static const int /*long*/ SHBrowseForFolder (BROWSEINFO lpbi) {
     if (IsUnicode) return SHBrowseForFolderW (lpbi);
     return SHBrowseForFolderA (lpbi);
 }
@@ -3169,7 +3238,7 @@
     return SHGetPathFromIDListA (pidl, pszPath1);
 }
 
-public static final int StartDoc (int /*long*/ hdc, DOCINFO lpdi) {
+public static const int StartDoc (int /*long*/ hdc, DOCINFO lpdi) {
     if (IsUnicode) return StartDocW (hdc, lpdi);
     return StartDocA (hdc, lpdi);
 }
@@ -3194,7 +3263,7 @@
     return SystemParametersInfoA (uiAction, uiParam, pvParam, fWinIni);
 }
 
-public static final int TranslateAccelerator (int /*long*/ hWnd, int /*long*/ hAccTable, MSG lpMsg) {
+public static const int TranslateAccelerator (int /*long*/ hWnd, int /*long*/ hAccTable, MSG lpMsg) {
     if (IsUnicode) return TranslateAcceleratorW (hWnd, hAccTable, lpMsg);
     return TranslateAcceleratorA (hWnd, hAccTable, lpMsg);
 }
@@ -4026,6 +4095,7 @@
     alias WINAPI.GetTextMetricsA GetTextMetrics;
     alias WINAPI.GetVersionExA GetVersionEx;
     alias WINAPI.GetWindowLongA GetWindowLong;
+    alias WINAPI.GetWindowLongPtrA GetWindowLongPtr;
     alias WINAPI.GetWindowTextA _GetWindowText;
     alias WINAPI.GetWindowTextLengthA GetWindowTextLength;
     alias WINAPI.GlobalAddAtomA GlobalAddAtom;
@@ -4062,6 +4132,7 @@
     alias WINAPI.SetMenuItemInfoA SetMenuItemInfo;
     alias WINAPI.SetPropA SetProp;
     alias WINAPI.SetWindowLongA SetWindowLong;
+    alias WINAPI.SetWindowLongPtrA SetWindowLongPtr;
     alias WINAPI.SetWindowTextA SetWindowText;
     alias WINAPI.SetWindowsHookExA SetWindowsHookEx;
     alias WINAPI.ShellExecuteExA ShellExecuteEx;
@@ -4129,6 +4200,7 @@
     alias WINAPI.GetTextMetricsW GetTextMetrics;
     alias WINAPI.GetVersionExW GetVersionEx;
     alias WINAPI.GetWindowLongW GetWindowLong;
+    alias WINAPI.GetWindowLongPtrW GetWindowLongPtr;
     alias WINAPI.GetWindowTextW _GetWindowText;
     alias WINAPI.GetWindowTextLengthW GetWindowTextLength;
     alias WINAPI.GlobalAddAtomW GlobalAddAtom;
@@ -4164,6 +4236,7 @@
     alias WINAPI.SendMessageW SendMessage;
     alias WINAPI.SetMenuItemInfoW SetMenuItemInfo;
     alias WINAPI.SetWindowLongW SetWindowLong;
+    alias WINAPI.SetWindowLongPtrW SetWindowLongPtr;
     alias WINAPI.SetWindowTextW SetWindowText;
     alias WINAPI.SetWindowsHookExW SetWindowsHookEx;
     alias WINAPI.SetPropW SetProp;
@@ -4318,8 +4391,15 @@
 // this function vars exist primarily for link error elimination
 //----------------------------------------------------------------------
 public static extern(Windows) {
+
+    BOOL function(
+        HIMC hIMC,
+        LPCANDIDATEFORM lpCandidate
+    ) ImmSetCandidateWindow;
+
 } // public static extern(Windows)
 
+
 static Symbol[] Symbols_CoreImm = [
 ];
 
@@ -4327,6 +4407,7 @@
 public static extern(Windows) BOOL function() SetProcessDPIAware;
 static Symbol[] Symbols_User32 = [
     { "SetProcessDPIAware", cast(void**)& SetProcessDPIAware, 6, 0 },
+    { "ImmSetCandidateWindow", cast(void**)& ImmSetCandidateWindow, 6, 0 },
 ];
 
 // Imm32.lib
@@ -4354,7 +4435,26 @@
 BOOL function( HIMC hIMC, LPCOMPOSITIONFORM lpCompForm ) ImmSetCompositionWindow;
 BOOL function( HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence ) ImmSetConversionStatus;
 BOOL function( HIMC hIMC, BOOL fOpen ) ImmSetOpenStatus;
-
+BOOL function(
+  HIMC hIMC,
+  DWORD dwAction,
+  DWORD dwIndex,
+  DWORD dwValue
+)ImmNotifyIME;
+
+LONG function(
+  HIMC hIMC,
+  DWORD dwIndex,
+  LPVOID lpBuf,
+  DWORD dwBufLen
+) ImmGetCompositionStringA;
+
+LONG function(
+  HIMC hIMC,
+  DWORD dwIndex,
+  LPVOID lpBuf,
+  DWORD dwBufLen
+) ImmGetCompositionStringW;
 }
 
 static Symbol[] Symbols_Imm32 = [
@@ -4373,6 +4473,9 @@
     { "ImmSetConversionStatus", cast(void**)& ImmSetConversionStatus, 5, 1 },
     { "ImmSetOpenStatus", cast(void**)& ImmSetOpenStatus, 5, 1 },
     { "ImmDisableTextFrameService", cast(void**)& ImmDisableTextFrameService, 5, 1 },
+    { "ImmNotifyIME", cast(void**)& ImmNotifyIME, 5, 1 },
+    { "ImmGetCompositionStringW", cast(void**)& ImmGetCompositionStringW, 5, 1 },
+    { "ImmGetCompositionStringA", cast(void**)& ImmGetCompositionStringA, 5, 1 },
 ];
 
 // kernel32 winxp/vista
@@ -5083,9 +5186,50 @@
     return fn(ppVtbl, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
 }
 
-
+public static int LOWORD (int /*long*/ l){
+    return l & 0xFFFF;
+}
+public static int HIWORD (int /*long*/ h){
+    return h >> 16;
+}
+//public static bool LPtoDP (int /*long*/ hdc, POINT lpPoints, int nCount);
+public static int MAKEWORD(int l, int h){
+    return ( h << 16 )|( l &0xFFFF );
+}
+public static int /*long*/ MAKEWPARAM(int l, int h);
+public static int /*long*/ MAKELPARAM(int l, int h);
+public static int /*long*/ MAKELRESULT(int l, int h);
+public static int GET_WHEEL_DELTA_WPARAM(int /*long*/ wParam);
+
+public static int GET_X_LPARAM(int /*long*/ lp){
+    return cast(short) (lp & 0xFFFF);
+}
+
+public static int GET_Y_LPARAM(int /*long*/ lp){
+    return cast(short) (lp >> 16);
+}
+
+alias WINAPI.GetOutlineTextMetrics GetOutlineTextMetrics;
+
+static bool TreeView_GetItemRect( HWND hwnd, HTREEITEM hitem, RECT* prc, bool code) {
+    *cast(HTREEITEM *)prc = hitem;
+    return cast(bool) SendMessage( hwnd, TVM_GETITEMRECT, code, cast(int)prc );
+}
+static int strlen( char* ptr ){
+    return tango.stdc.string.strlen( ptr );
+}
+alias WINAPI.GetLayeredWindowAttributes GetLayeredWindowAttributes;
+alias WINAPI.SetLayeredWindowAttributes SetLayeredWindowAttributes;
+
+static void POINTSTOPOINT( inout POINT pt, int pts) {
+    pt.x = cast(SHORT) LOWORD(pts);
+    pt.y = cast(SHORT) HIWORD(pts);
+}
+
+alias WINAPI.GetScrollBarInfo GetScrollBarInfo;
+alias WINAPI.PrintWindow PrintWindow;
 } // END of OS
-
+//-----------------------------------------------------------------------------
 import tango.sys.win32.CodePage : CodePage;
 private import tango.text.convert.Utf;
 private import tango.stdc.stringz;
@@ -5293,8 +5437,11 @@
 
 
 TCHAR[] NewTCHARs( uint codepage, uint len ){
-    return new TCHAR[ len ];
-}
-
-
-
+    auto res = new TCHAR[ len ];
+    res[] = '\0';
+    return res;
+}
+
+
+
+
--- a/dwt/internal/win32/WINAPI.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/win32/WINAPI.d	Sat May 17 17:34:28 2008 +0200
@@ -2099,18 +2099,17 @@
     DEVMODE *lpInitData
                    // pointer to optional printer data
 );
-    HBITMAP CreateDIBSection(
-    HDC hdc,          // handle to device context
-    BITMAPINFO *pbmi,
-                // pointer to structure containing bitmap size,
-                // format, and color data
-    UINT iUsage,      // color data type indicator: RGB values or
-                // palette indexes
-    VOID *ppvBits,    // pointer to variable to receive a pointer to
-                // the bitmap's bit values
-    HANDLE hSection,  // optional handle to a file mapping object
-    DWORD dwOffset    // offset to the bitmap bit values within the
-                // file mapping object
+HBITMAP CreateDIBSection(
+    HDC hdc,           // handle to device context
+    BITMAPINFO *pbmi,  // pointer to structure containing bitmap size,
+                       // format, and color data
+    UINT iUsage,       // color data type indicator: RGB values or
+                       // palette indexes
+    VOID **ppvBits,    // pointer to variable to receive a pointer to
+                       // the bitmap's bit values
+    HANDLE hSection,   // optional handle to a file mapping object
+    DWORD dwOffset     // offset to the bitmap bit values within the
+                       // file mapping object
 );
 HANDLE CreateEventA(
   LPSECURITY_ATTRIBUTES lpEventAttributes,
@@ -2858,6 +2857,16 @@
 );
 LONG GetWindowLongA(HWND hWnd, int nIndex);
 LONG GetWindowLongW(HWND hWnd, int nIndex);
+
+LONG_PTR GetWindowLongPtrA(
+    HWND hWnd,
+    int nIndex
+);
+LONG_PTR GetWindowLongPtrW(
+    HWND hWnd,
+    int nIndex
+);
+
 BOOL GetWindowPlacement(
     HWND hWnd,
     WINDOWPLACEMENT *lpwndpl
@@ -3641,6 +3650,19 @@
     int nIndex,
     LONG dwNewLong
 );
+
+LONG_PTR SetWindowLongPtrA(
+    HWND hWnd,
+    int nIndex,
+    LONG_PTR dwNewLong
+);
+
+LONG_PTR SetWindowLongPtrW(
+    HWND hWnd,
+    int nIndex,
+    LONG_PTR dwNewLong
+);
+
 BOOL SetWindowPlacement(
     HWND hWnd,
     WINDOWPLACEMENT *lpwndpl
@@ -3799,6 +3821,36 @@
 SHORT VkKeyScanA(char ch);
 SHORT VkKeyScanW(wchar ch);
 BOOL WaitMessage();
+
+UINT GetOutlineTextMetrics(
+  HDC                  hdc,
+  UINT                 cbData,
+  LPOUTLINETEXTMETRICW lpOTM
+);
+
+BOOL GetLayeredWindowAttributes(
+    HWND hwnd,
+    COLORREF *pcrKey,
+    BYTE *pbAlpha,
+    DWORD *pdwFlags
+);
+BOOL SetLayeredWindowAttributes(
+    HWND hwnd,
+    COLORREF crKey,
+    BYTE bAlpha,
+    DWORD dwFlags
+);
+BOOL GetScrollBarInfo(
+    HWND hwnd,
+    LONG idObject,
+    PSCROLLBARINFO psbi
+);
+BOOL PrintWindow(
+  HWND hwnd,               // Window to copy
+  HDC  hdcBlt,             // HDC to print into
+  UINT nFlags              // Optional flags
+);
+
 }
 
 extern (C)
--- a/dwt/internal/win32/WINTYPES.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/internal/win32/WINTYPES.d	Sat May 17 17:34:28 2008 +0200
@@ -11192,46 +11192,52 @@
 // alias TEXTMETRIC TTEXTMETRIC;
 // alias TEXTMETRIC* PTEXTMETRIC;
 
-struct OUTLINETEXTMETRIC
-{
-    UINT otmSize;
-    TEXTMETRIC otmTextMetrics;
-    ubyte otmFiller;
-    PANOSE otmPanoseNumber;
-    UINT otmfsSelection;
-    UINT otmfsType;
-    int otmsCharSlopeRise;
-    int otmsCharSlopeRun;
-    int otmItalicAngle;
-    UINT otmEMSquare;
-    int otmAscent;
-    int otmDescent;
-    UINT otmLineGap;
-    UINT otmsCapEmHeight;
-    UINT otmsXHeight;
-    RECT otmrcFontBox;
-    int otmMacAscent;
-    int otmMacDescent;
-    UINT otmMacLineGap;
-    UINT otmusMinimumPPEM;
-    POINT otmptSubscriptSize;
-    POINT otmptSubscriptOffset;
-    POINT otmptSuperscriptSize;
-    POINT otmptSuperscriptOffset;
-    UINT otmsStrikeoutSize;
-    int otmsStrikeoutPosition;
-    int otmsUnderscoreSize;
-    int otmsUnderscorePosition;
-    PSTR otmpFamilyName;
-    PSTR otmpFaceName;
-    PSTR otmpStyleName;
-    PSTR otmpFullName;
+struct OUTLINETEXTMETRICW {
+  UINT       otmSize;
+  TEXTMETRIC otmTextMetrics;
+  BYTE       otmFiller;
+  PANOSE     otmPanoseNumber;
+  UINT       otmfsSelection;
+  UINT       otmfsType;
+  int        otmsCharSlopeRise;
+  int        otmsCharSlopeRun;
+  int        otmItalicAngle;
+  UINT       otmEMSquare;
+  int        otmAscent;
+  int        otmDescent;
+  UINT       otmLineGap;
+  UINT       otmsCapEmHeight;
+  UINT       otmsXHeight;
+  RECT       otmrcFontBox;
+  int        otmMacAscent;
+  int        otmMacDescent;
+  UINT       otmMacLineGap;
+  UINT       otmusMinimumPPEM;
+  POINT      otmptSubscriptSize;
+  POINT      otmptSubscriptOffset;
+  POINT      otmptSuperscriptSize;
+  POINT      otmptSuperscriptOffset;
+  UINT       otmsStrikeoutSize;
+  int        otmsStrikeoutPosition;
+  int        otmsUnderscoreSize;
+  int        otmsUnderscorePosition;
+  PSTR       otmpFamilyName;
+  PSTR       otmpFaceName;
+  PSTR       otmpStyleName;
+  PSTR       otmpFullName;
 }
 
 alias OUTLINETEXTMETRIC* LPOUTLINETEXTMETRIC;
 alias OUTLINETEXTMETRIC _OUTLINETEXTMETRIC;
 alias OUTLINETEXTMETRIC TOUTLINETEXTMETRIC;
 alias OUTLINETEXTMETRIC* POUTLINETEXTMETRIC;
+version(ANSI){
+    alias OUTLINETEXTMETRICA OUTLINETEXTMETRIC;
+    alias OUTLINETEXTMETRICA* LPOUTLINETEXTMETRICA;
+}else {
+    alias OUTLINETEXTMETRICW OUTLINETEXTMETRIC;
+    alias OUTLINETEXTMETRICW* LPOUTLINETEXTMETRICW;
+}
 
 struct OVERLAPPED
 {
@@ -12613,6 +12619,7 @@
     UINT flags;
 }
 
+alias TC_HITTESTINFO TCHITTESTINFO;
 alias TC_HITTESTINFO _TC_HITTESTINFO;
 alias TC_HITTESTINFO TTCHITTESTINFO;
 alias TC_HITTESTINFO* PTCHITTESTINFO;
@@ -15855,6 +15862,82 @@
 //     alias WNDCLASSW WNDCLASS_T;
 // }
 
+enum TF_DA_COLORTYPE {
+  TF_CT_NONE = 0,
+  TF_CT_SYSCOLOR = 1,
+  TF_CT_COLORREF = 2
+}
+
+enum TF_DA_LINESTYLE {
+  TF_LS_NONE = 0,
+  TF_LS_SOLID = 1,
+  TF_LS_DOT = 2,
+  TF_LS_DASH = 3,
+  TF_LS_SQUIGGLE = 4
+}
+
+enum TF_DA_ATTR_INFO {
+  TF_ATTR_INPUT = 0,
+  TF_ATTR_TARGET_CONVERTED = 1,
+  TF_ATTR_CONVERTED = 2,
+  TF_ATTR_TARGET_NOTCONVERTED = 3,
+  TF_ATTR_INPUT_ERROR = 4,
+  TF_ATTR_FIXEDCONVERTED = 5,
+  TF_ATTR_OTHER = -1
+}
+
+struct TF_DA_COLOR {
+  TF_DA_COLORTYPE type;
+  union {
+    int nIndex;
+    COLORREF cr;
+  };
+}
+
+struct TF_DISPLAYATTRIBUTE{
+  TF_DA_COLOR crText;
+  TF_DA_COLOR crBk;
+  TF_DA_LINESTYLE lsStyle;
+  BOOL fBoldLine;
+  TF_DA_COLOR crLine;
+  TF_DA_ATTR_INFO bAttr;
+}
+
+struct NMTTCUSTOMDRAW {
+    NMCUSTOMDRAW nmcd;
+    UINT uDrawFlags;
+}
+alias NMTTCUSTOMDRAW* LPNMTTCUSTOMDRAW;
+
+struct SHDRAGIMAGE {
+    SIZE sizeDragImage;
+    POINT ptOffset;
+    HBITMAP hbmpDragImage;
+    COLORREF crColorKey;
+}
+
+const CCHILDREN_SCROLLBAR = 5;
+struct SCROLLBARINFO {
+    DWORD cbSize;
+    RECT rcScrollBar;
+    int dxyLineButton;
+    int xyThumbTop;
+    int xyThumbBottom;
+    int reserved;
+    DWORD rgstate[CCHILDREN_SCROLLBAR+1];
+}
+alias SCROLLBARINFO* PSCROLLBARINFO;
+
+struct NMTREEVIEW {
+    NMHDR hdr;
+    UINT action;
+    TVITEM itemOld;
+    TVITEM itemNew;
+    POINT ptDrag;
+}
+alias NMTREEVIEW* PNMTREEVIEW;
+alias NMTREEVIEW* LPNMTREEVIEW;
+
 }   // end of extern(Windows)
 
 
--- a/dwt/layout/RowLayout.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/layout/RowLayout.d	Sat May 17 17:34:28 2008 +0200
@@ -138,6 +138,17 @@
     public bool fill = false;
 
     /**
+     * center specifies whether the controls in a row should be
+     * centered vertically in each cell for horizontal layouts,
+     * or centered horizontally in each cell for vertical layouts.
+     *
+     * The default value is false.
+     * 
+     * @since 3.4
+     */
+    public bool center = false;
+    
+    /**
      * justify specifies whether the controls in a row should be
      * fully justified, with any extra space placed between the controls.
      *
@@ -268,7 +279,7 @@
     int [] wraps = null;
     bool wrapped = false;
     Rectangle [] bounds = null;
-    if (move && (justify || fill)) {
+    if (move && (justify || fill || center)) {
         bounds = new Rectangle [count];
         wraps = new int [count];
     }
@@ -282,17 +293,17 @@
         }
         if (wrap && (i !is 0) && (x + childWidth > width)) {
             wrapped = true;
-            if (move && (justify || fill)) wraps [i - 1] = maxHeight;
+            if (move && (justify || fill || center)) wraps [i - 1] = maxHeight;
             x = marginLeft + marginWidth;
             y += spacing + maxHeight;
             if (pack) maxHeight = 0;
         }
-        if (pack || fill) {
+        if (pack || fill || center) {
             maxHeight = Math.max (maxHeight, childHeight);
         }
         if (move) {
             int childX = x + clientX, childY = y + clientY;
-            if (justify || fill) {
+            if (justify || fill || center) {
                 bounds [i] = new Rectangle (childX, childY, childWidth, childHeight);
             } else {
                 child.setBounds (childX, childY, childWidth, childHeight);
@@ -303,13 +314,13 @@
     }
     maxX = Math.max (clientX + marginLeft + marginWidth, maxX - spacing);
     if (!wrapped) maxX += marginRight + marginWidth;
-    if (move && (justify || fill)) {
+    if (move && (justify || fill || center)) {
         int space = 0, margin = 0;
         if (!wrapped) {
             space = Math.max (0, (width - maxX) / (count + 1));
             margin = Math.max (0, ((width - maxX) % (count + 1)) / 2);
         } else {
-            if (fill || justify) {
+            if (fill || justify || center) {
                 int last = 0;
                 if (count > 0) wraps [count - 1] = maxHeight;
                 for (int i=0; i<count; i++) {
@@ -325,7 +336,13 @@
                         }
                         for (int j=last; j<=i; j++) {
                             if (justify) bounds [j].x += (space * (j - last + 1)) + margin;
-                            if (fill) bounds [j].height = wraps [i];
+                            if (fill) {
+                                bounds [j].height = wraps [i];
+                            } else {
+                                if (center) {
+                                    bounds [j].y += Math.max (0, (wraps [i] - bounds [j].height) / 2);
+                                }
+                            }
                         }
                         last = i + 1;
                     }
@@ -335,7 +352,13 @@
         for (int i=0; i<count; i++) {
             if (!wrapped) {
                 if (justify) bounds [i].x += (space * (i + 1)) + margin;
-                if (fill) bounds [i].height = maxHeight;
+                if (fill) {
+                    bounds [i].height = maxHeight;
+                } else {
+                    if (center) {
+                        bounds [i].y += Math.max (0, (maxHeight - bounds [i].height) / 2);
+                    }
+                }
             }
             children [i].setBounds (bounds [i]);
         }
@@ -375,7 +398,7 @@
     int [] wraps = null;
     bool wrapped = false;
     Rectangle [] bounds = null;
-    if (move && (justify || fill)) {
+    if (move && (justify || fill || center)) {
         bounds = new Rectangle [count];
         wraps = new int [count];
     }
@@ -389,17 +412,17 @@
         }
         if (wrap && (i !is 0) && (y + childHeight > height)) {
             wrapped = true;
-            if (move && (justify || fill)) wraps [i - 1] = maxWidth;
+            if (move && (justify || fill || center)) wraps [i - 1] = maxWidth;
             x += spacing + maxWidth;
             y = marginTop + marginHeight;
             if (pack) maxWidth = 0;
         }
-        if (pack || fill) {
+        if (pack || fill || center) {
             maxWidth = Math.max (maxWidth, childWidth);
         }
         if (move) {
             int childX = x + clientX, childY = y + clientY;
-            if (justify || fill) {
+            if (justify || fill || center) {
                 bounds [i] = new Rectangle (childX, childY, childWidth, childHeight);
             } else {
                 child.setBounds (childX, childY, childWidth, childHeight);
@@ -410,13 +433,13 @@
     }
     maxY = Math.max (clientY + marginTop + marginHeight, maxY - spacing);
     if (!wrapped) maxY += marginBottom + marginHeight;
-    if (move && (justify || fill)) {
+    if (move && (justify || fill || center)) {
         int space = 0, margin = 0;
         if (!wrapped) {
             space = Math.max (0, (height - maxY) / (count + 1));
             margin = Math.max (0, ((height - maxY) % (count + 1)) / 2);
         } else {
-            if (fill || justify) {
+            if (fill || justify || center) {
                 int last = 0;
                 if (count > 0) wraps [count - 1] = maxWidth;
                 for (int i=0; i<count; i++) {
@@ -432,7 +455,13 @@
                         }
                         for (int j=last; j<=i; j++) {
                             if (justify) bounds [j].y += (space * (j - last + 1)) + margin;
-                            if (fill) bounds [j].width = wraps [i];
+                            if (fill) {
+                                bounds [j].width = wraps [i];
+                            } else {
+                                if (center) {
+                                    bounds [j].x += Math.max (0, (wraps [i] - bounds [j].width) / 2);
+                                }
+                            }
                         }
                         last = i + 1;
                     }
@@ -442,7 +471,14 @@
         for (int i=0; i<count; i++) {
             if (!wrapped) {
                 if (justify) bounds [i].y += (space * (i + 1)) + margin;
-                if (fill) bounds [i].width = maxWidth;
+                if (fill) {
+                    bounds [i].width = maxWidth;
+                } else {
+                    if (center) {
+                        bounds [i].x += Math.max (0, (maxWidth - bounds [i].width) / 2);
+                    }
+                }
+
             }
             children [i].setBounds (bounds [i]);
         }
--- a/dwt/printing/PrintDialog.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/printing/PrintDialog.d	Sat May 17 17:34:28 2008 +0200
@@ -38,6 +38,7 @@
  */
 
 public class PrintDialog : Dialog {
+    PrinterData printerData;
     int scope_ = PrinterData.ALL_PAGES;
     int startPage = 1, endPage = 1;
     bool printToFile = false;
@@ -97,15 +98,39 @@
 }
 
 /**
+ * Sets the printer data that will be used when the dialog
+ * is opened.
+ *
+ * @param data the data that will be used when the dialog is opened
+ *
+ * @since 3.4
+ */
+public void setPrinterData(PrinterData data) {
+    this.printerData = data;
+}
+
+/**
+ * Returns the printer data that will be used when the dialog
+ * is opened.
+ *
+ * @return the data that will be used when the dialog is opened
+ *
+ * @since 3.4
+ */
+public PrinterData getPrinterData() {
+    return printerData;
+}
+
+/**
  * Returns the print job scope that the user selected
  * before pressing OK in the dialog. This will be one
  * of the following values:
  * <dl>
- * <dt><code>ALL_PAGES</code></dt>
+ * <dt><code>PrinterData.ALL_PAGES</code></dt>
  * <dd>Print all pages in the current document</dd>
- * <dt><code>PAGE_RANGE</code></dt>
+ * <dt><code>PrinterData.PAGE_RANGE</code></dt>
  * <dd>Print the range of pages specified by startPage and endPage</dd>
- * <dt><code>SELECTION</code></dt>
+ * <dt><code>PrinterData.SELECTION</code></dt>
  * <dd>Print the current selection</dd>
  * </dl>
  *
@@ -120,11 +145,11 @@
  * setting when the dialog is opened. This can have one of
  * the following values:
  * <dl>
- * <dt><code>ALL_PAGES</code></dt>
+ * <dt><code>PrinterData.ALL_PAGES</code></dt>
  * <dd>Print all pages in the current document</dd>
- * <dt><code>PAGE_RANGE</code></dt>
+ * <dt><code>PrinterData.PAGE_RANGE</code></dt>
  * <dd>Print the range of pages specified by startPage and endPage</dd>
- * <dt><code>SELECTION</code></dt>
+ * <dt><code>PrinterData.SELECTION</code></dt>
  * <dd>Print the current selection</dd>
  * </dl>
  *
@@ -139,7 +164,7 @@
  * before pressing OK in the dialog.
  * <p>
  * This value can be from 1 to the maximum number of pages for the platform.
- * Note that it is only valid if the scope is <code>PAGE_RANGE</code>.
+ * Note that it is only valid if the scope is <code>PrinterData.PAGE_RANGE</code>.
  * </p>
  *
  * @return the start page setting that the user selected
@@ -153,7 +178,7 @@
  * is opened.
  * <p>
  * This value can be from 1 to the maximum number of pages for the platform.
- * Note that it is only valid if the scope is <code>PAGE_RANGE</code>.
+ * Note that it is only valid if the scope is <code>PrinterData.PAGE_RANGE</code>.
  * </p>
  *
  * @param startPage the startPage setting when the dialog is opened
@@ -167,7 +192,7 @@
  * before pressing OK in the dialog.
  * <p>
  * This value can be from 1 to the maximum number of pages for the platform.
- * Note that it is only valid if the scope is <code>PAGE_RANGE</code>.
+ * Note that it is only valid if the scope is <code>PrinterData.PAGE_RANGE</code>.
  * </p>
  *
  * @return the end page setting that the user selected
@@ -181,7 +206,7 @@
  * is opened.
  * <p>
  * This value can be from 1 to the maximum number of pages for the platform.
- * Note that it is only valid if the scope is <code>PAGE_RANGE</code>.
+ * Note that it is only valid if the scope is <code>PrinterData.PAGE_RANGE</code>.
  * </p>
  *
  * @param endPage the end page setting when the dialog is opened
@@ -234,6 +259,17 @@
     pd.lStructSize = PRINTDLG.sizeof;
     Control parent = getParent();
     if (parent !is null) pd.hwndOwner = parent.handle;
+    void* lpInitData;
+    auto hHeap = OS.GetProcessHeap();
+    if (printerData !is null) {
+        byte buffer [] = printerData.otherData;
+        if (buffer !is null && buffer.length !is 0) {
+            /* If user setup info from a previous print dialog was specified, restore the DEVMODE struct. */
+            lpInitData = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, buffer.length);
+            OS.MoveMemory(lpInitData, buffer.ptr, buffer.length);
+            pd.hDevMode = lpInitData;
+        }
+    }
     pd.Flags = OS.PD_USEDEVMODECOPIESANDCOLLATE;
     if (printToFile) pd.Flags |= OS.PD_PRINTTOFILE;
     switch (scope_) {
@@ -328,6 +364,7 @@
         data.otherData = new byte[size];
         OS.MoveMemory(data.otherData.ptr, ptr, size);
         OS.GlobalUnlock(hMem);
+        if (lpInitData !is null) OS.HeapFree(hHeap, 0, lpInitData);
 
         endPage = data.endPage;
         printToFile = data.printToFile;
--- a/dwt/printing/Printer.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/printing/Printer.d	Sat May 17 17:34:28 2008 +0200
@@ -18,6 +18,7 @@
 import dwt.DWTException;
 import dwt.graphics.Device;
 import dwt.graphics.DeviceData;
+import dwt.graphics.Font;
 import dwt.graphics.GCData;
 import dwt.graphics.Point;
 import dwt.graphics.Rectangle;
@@ -254,7 +255,7 @@
             data.style |= DWT.LEFT_TO_RIGHT;
         }
         data.device = this;
-        data.hFont = OS.GetCurrentObject(handle, OS.OBJ_FONT);
+        data.font = Font.win32_new(this, OS.GetCurrentObject(handle, OS.OBJ_FONT));
         isGCCreated = true;
     }
     return handle;
--- a/dwt/printing/PrinterData.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/printing/PrinterData.d	Sat May 17 17:34:28 2008 +0200
@@ -130,6 +130,10 @@
      * private, platform-specific data
      * On Windows, this contains a copy of the DEVMODE struct
      * returned from the <code>PrintDialog</code>.
+     * On GTK, this contains a copy of the print_settings and page_setup
+     * returned from the <code>PrintDialog</code>.
+     * On OS X Carbon, this contains a copy of the PrintSettings and PageFormat
+     * returned from the <code>PrintDialog</code>.
      * This field is not currently used on the X/Window System.
      */
     byte [] otherData;
--- a/dwt/program/Program.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/program/Program.d	Sat May 17 17:34:28 2008 +0200
@@ -42,10 +42,11 @@
     TCHAR[] pszOut = NewTCHARs(0, 1024);
     uint[1] pcchOut;
     pcchOut[0] = pszOut.length;
-    int result = OS.AssocQueryString(OS.ASSOCF_NOTRUNCATE, assocStr, key.ptr, null, pszOut.ptr, pcchOut.ptr);
+    int flags = OS.ASSOCF_NOTRUNCATE | OS.ASSOCF_INIT_IGNOREUNKNOWN;
+    int result = OS.AssocQueryString (flags, assocStr, key.ptr, null, pszOut.ptr, pcchOut.ptr);
     if (result is OS.E_POINTER) {
         pszOut = NewTCHARs(0, pcchOut [0]);
-        result = OS.AssocQueryString(OS.ASSOCF_NOTRUNCATE, assocStr, key.ptr, null, pszOut.ptr, pcchOut.ptr);
+        result = OS.AssocQueryString (flags, assocStr, key.ptr, null, pszOut.ptr, pcchOut.ptr);
     }
     if (result is 0) {
         if (!OS.IsWinCE && expand) {
@@ -252,13 +253,12 @@
 }
 
 /**
- * Launches the executable associated with the file in
- * the operating system.  If the file is an executable,
- * then the executable is launched.  Note that a <code>Display</code>
- * must already exist to guarantee that this method returns
- * an appropriate result.
+ * Launches the operating system executable associated with the file or
+ * URL (http:// or https://).  If the file is an executable then the
+ * executable is launched.  Note that a <code>Display</code> must already
+ * exist to guarantee that this method returns an appropriate result.
  *
- * @param fileName the file or program name
+ * @param fileName the file or program name or URL (http:// or https://)
  * @return <code>true</code> if the file is launched, otherwise <code>false</code>
  *
  * @exception IllegalArgumentException <ul>
@@ -359,6 +359,12 @@
             nIconIndex = Integer.parseInt (iconIndex);
         } catch (NumberFormatException e) {}
     }
+    int length = fileName.length;
+    if (length !is 0 && fileName.charAt (0) is '\"') {
+        if (fileName.charAt (length - 1) is '\"') {
+            fileName = fileName.substring (1, length - 1);
+        }
+    }
     /* Use the character encoding for the default locale */
     TCHAR[] lpszFile = StrToTCHARs (0, fileName, true);
     HICON [1] phiconSmall, phiconLarge;
--- a/dwt/widgets/Button.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/Button.d	Sat May 17 17:34:28 2008 +0200
@@ -63,7 +63,7 @@
     String text = "", message = "";
     Image image, image2, disabledImage;
     ImageList imageList;
-    bool ignoreMouse;
+    bool ignoreMouse, grayed;
     static const int MARGIN = 4;
     private static /+const+/ int CHECK_WIDTH, CHECK_HEIGHT;
     static const int ICON_WIDTH = 128, ICON_HEIGHT = 128;
@@ -504,8 +504,36 @@
 }
 
 override void createHandle () {
+    /*
+    * Feature in Windows.  When a button is created,
+    * it clears the UI state for all controls in the
+    * shell by sending WM_CHANGEUISTATE with UIS_SET,
+    * UISF_HIDEACCEL and UISF_HIDEFOCUS to the parent.
+    * This is undocumented and unexpected.  The fix
+    * is to ignore the WM_CHANGEUISTATE, when sent
+    * from CreateWindowEx().
+    */
+    parent.state |= IGNORE_WM_CHANGEUISTATE;
     super.createHandle ();
-    if ((style & DWT.PUSH) is 0) state |= THEME_BACKGROUND;
+    parent.state &= ~IGNORE_WM_CHANGEUISTATE;
+
+    /* Set the theme background */
+    if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+        /*
+        * NOTE: On Vista this causes problems when the tab
+        * key is pressed for push buttons so disable the
+        * theme background drawing for these widgets for
+        * now.
+        */
+        if (!OS.IsWinCE && OS.WIN32_VERSION < OS.VERSION (6, 0)) {
+            state |= THEME_BACKGROUND;
+        } else {
+            if ((style & (DWT.PUSH | DWT.TOGGLE)) is 0) {
+                state |= THEME_BACKGROUND;
+            }
+        }
+    }
+
     /*
     * Bug in Windows.  For some reason, the HBRUSH that
     * is returned from WM_CTRLCOLOR is misaligned when
@@ -521,6 +549,23 @@
     if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
         if ((style & DWT.RADIO) !is 0) state |= DRAW_BACKGROUND;
     }
+
+    /*
+    * Feature in Windows.  Push buttons draw border around
+    * the button using the default background color instead
+    * of using the color provided by WM_CTRLCOLOR.  The fix
+    * is to draw the background in WM_CTRLCOLOR.
+    *
+    * NOTE: On Vista this causes problems when the tab key
+    * is pressed for push buttons so disable the fix for now.
+    */
+    if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+        if (!OS.IsWinCE && OS.WIN32_VERSION < OS.VERSION (6, 0)) {
+            if ((style & (DWT.PUSH | DWT.TOGGLE)) !is 0) {
+                state |= DRAW_BACKGROUND;
+            }
+        }
+    }
 }
 
 override int defaultBackground () {
@@ -625,6 +670,24 @@
 }
 
 /**
+ * Returns <code>true</code> if the receiver is grayed,
+ * and false otherwise. When the widget does not have
+ * the <code>CHECK</code> style, return false.
+ *
+ * @return the grayed state of the checkbox
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+public bool getGrayed () {
+    checkWidget();
+    if ((style & DWT.CHECK) is 0) return false;
+    return grayed;
+}
+
+/**
  * Returns the receiver's image if it has one, or null
  * if it does not.
  *
@@ -682,8 +745,8 @@
 public bool getSelection () {
     checkWidget ();
     if ((style & (DWT.CHECK | DWT.RADIO | DWT.TOGGLE)) is 0) return false;
-    int state = OS.SendMessage (handle, OS.BM_GETCHECK, 0, 0);
-    return (state & OS.BST_CHECKED) !is 0;
+    int /*long*/ flags = OS.SendMessage (handle, OS.BM_GETCHECK, 0, 0);
+    return flags !is OS.BST_UNCHECKED;
 }
 
 /**
@@ -705,8 +768,7 @@
 }
 
 override bool isTabItem () {
-    //TEMPORARY CODE
-    //if ((style & DWT.PUSH) !is 0) return true;
+    if ((style & DWT.PUSH) !is 0) return isTabGroup ();
     return super.isTabItem ();
 }
 
@@ -728,6 +790,20 @@
     return CharacterToUpper (key) is CharacterToUpper (mnemonic);
 }
 
+void printWidget (HWND hwnd, HDC hDC) {
+    /*
+    * Bug in Windows.  For some reason, PrintWindow() fails
+    * when it is called on a push button.  The fix is to
+    * detect the failure and use WM_PRINT instead.  Note
+    * that WM_PRINT cannot be used all the time because it
+    * fails for browser controls when the browser has focus.
+    */
+    if (!OS.PrintWindow (hwnd, hDC, 0)) {
+        int flags = OS.PRF_CLIENT | OS.PRF_NONCLIENT | OS.PRF_ERASEBKGND | OS.PRF_CHILDREN;
+        OS.SendMessage (hwnd, OS.WM_PRINT, hDC, flags);
+    }
+}
+
 override void releaseWidget () {
     super.releaseWidget ();
     if (imageList !is null) imageList.dispose ();
@@ -906,6 +982,30 @@
 }
 
 /**
+ * Sets the grayed state of the receiver.  This state change
+ * only applies if the control was created with the DWT.CHECK
+ * style.
+ *
+ * @param grayed the new grayed state
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+public void setGrayed (bool grayed) {
+    checkWidget ();
+    if ((style & DWT.CHECK) is 0) return;
+    this.grayed = grayed;
+    int /*long*/ flags = OS.SendMessage (handle, OS.BM_GETCHECK, 0, 0);
+    if (grayed) {
+        if (flags is OS.BST_CHECKED) updateSelection (OS.BST_INDETERMINATE);
+    } else {
+        if (flags is OS.BST_INDETERMINATE) updateSelection (OS.BST_CHECKED);
+    }
+}
+
+/**
  * Sets the widget message. When the widget is created
  * with the style <code>DWT.COMMAND</code>, the message text
  * is displayed to provide further information for the user.
@@ -980,16 +1080,10 @@
     checkWidget ();
     if ((style & (DWT.CHECK | DWT.RADIO | DWT.TOGGLE)) is 0) return;
     int flags = selected ? OS.BST_CHECKED : OS.BST_UNCHECKED;
-    /*
-    * Feature in Windows. When BM_SETCHECK is used
-    * to set the checked state of a radio or check
-    * button, it sets the WM_TABSTOP style.  This
-    * is undocumented and unwanted.  The fix is
-    * to save and restore the window style bits.
-    */
-    int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
-    OS.SendMessage (handle, OS.BM_SETCHECK, flags, 0);
-    OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+    if ((style & DWT.CHECK) !is 0) {
+        if (selected && grayed) flags = OS.BST_INDETERMINATE;
+    }
+    updateSelection (flags);
 }
 
 /**
@@ -1038,6 +1132,35 @@
     _setText (string);
 }
 
+void updateSelection (int flags) {
+    if (flags !is OS.SendMessage (handle, OS.BM_GETCHECK, 0, 0)) {
+        /*
+        * Feature in Windows. When BM_SETCHECK is used
+        * to set the checked state of a radio or check
+        * button, it sets the WM_TABSTOP style.  This
+        * is undocumented and unwanted.  The fix is
+        * to save and restore the window style bits.
+        */
+        int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+        if ((style & DWT.CHECK) !is 0) {
+            if (flags is OS.BST_INDETERMINATE) {
+                bits &= ~OS.BS_CHECKBOX;
+                bits |= OS.BS_3STATE;
+            } else {
+                bits |= OS.BS_CHECKBOX;
+                bits &= ~OS.BS_3STATE;
+            }
+            if (bits !is OS.GetWindowLong (handle, OS.GWL_STYLE)) {
+                OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+            }
+        }
+        OS.SendMessage (handle, OS.BM_SETCHECK, flags, 0);
+        if (bits !is OS.GetWindowLong (handle, OS.GWL_STYLE)) {
+            OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+        }
+    }
+}
+
 override int widgetStyle () {
     int bits = super.widgetStyle ();
     if ((style & DWT.FLAT) !is 0) bits |= OS.BS_FLAT;
@@ -1184,7 +1307,7 @@
             }
             if (redraw) {
                 OS.InvalidateRect (handle, null, false);
-                int code = OS.DefWindowProc (handle, OS.WM_UPDATEUISTATE, wParam, lParam);
+                int /*long*/ code = OS.DefWindowProc (handle, OS.WM_UPDATEUISTATE, wParam, lParam);
                 return new LRESULT (code);
             }
         }
@@ -1193,7 +1316,7 @@
 }
 
 override LRESULT wmCommandChild (int wParam, int lParam) {
-    int code = wParam >> 16;
+    int code = OS.HIWORD (wParam);
     switch (code) {
         case OS.BN_CLICKED:
         case OS.BN_DOUBLECLICKED:
--- a/dwt/widgets/Canvas.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/Canvas.d	Sat May 17 17:34:28 2008 +0200
@@ -24,6 +24,7 @@
 import dwt.widgets.Caret;
 import dwt.widgets.Control;
 import dwt.widgets.Display;
+import dwt.widgets.IME;
 
 import dwt.dwthelper.utils;
 
@@ -53,6 +54,7 @@
     alias Composite.windowProc windowProc;
 
     Caret caret;
+    IME ime;
 
 /**
  * Prevents uninitialized instances from being created outside the package.
@@ -103,37 +105,6 @@
 }
 
 /**
- * Returns the caret.
- * <p>
- * The caret for the control is automatically hidden
- * and shown when the control is painted or resized,
- * when focus is gained or lost and when an the control
- * is scrolled.  To avoid drawing on top of the caret,
- * the programmer must hide and show the caret when
- * drawing in the window any other time.
- * </p>
- *
- * @return the caret
- *
- * @exception DWTException <ul>
- *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
- * </ul>
- */
-public Caret getCaret () {
-    checkWidget ();
-    return caret;
-}
-
-override void releaseChildren (bool destroy) {
-    if (caret !is null) {
-        caret.release (false);
-        caret = null;
-    }
-    super.releaseChildren (destroy);
-}
-
-/**
  * Fills the interior of the rectangle specified by the arguments,
  * with the receiver's background.
  *
@@ -166,6 +137,58 @@
 }
 
 /**
+ * Returns the caret.
+ * <p>
+ * The caret for the control is automatically hidden
+ * and shown when the control is painted or resized,
+ * when focus is gained or lost and when an the control
+ * is scrolled.  To avoid drawing on top of the caret,
+ * the programmer must hide and show the caret when
+ * drawing in the window any other time.
+ * </p>
+ *
+ * @return the caret
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+public Caret getCaret () {
+    checkWidget ();
+    return caret;
+}
+
+/**
+ * Returns the IME.
+ *
+ * @return the IME
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @since 3.4
+ */
+public IME getIME () {
+    checkWidget ();
+    return ime;
+}
+
+void releaseChildren (bool destroy) {
+    if (caret !is null) {
+        caret.release (false);
+        caret = null;
+    }
+    if (ime !is null) {
+        ime.release (false);
+        ime = null;
+    }
+    super.releaseChildren (destroy);
+}
+
+/**
  * Scrolls a rectangular area of the receiver by first copying
  * the source area to the destination and then causing the area
  * of the source which is not covered by the destination to
@@ -296,6 +319,27 @@
     super.setFont (font);
 }
 
+/**
+ * Sets the receiver's IME.
+ *
+ * @param ime the new IME for the receiver, may be null
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the IME has been disposed</li>
+ * </ul>
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @since 3.4
+ */
+public void setIME (IME ime) {
+    checkWidget ();
+    if (ime !is null && ime.isDisposed()) error(DWT.ERROR_INVALID_ARGUMENT);
+    this.ime = ime;
+}
+
 override int windowProc (HWND hwnd, int msg, int wParam, int lParam) {
     if (msg is Display.SWT_RESTORECARET) {
         if ((state & CANVAS) !is 0) {
@@ -309,8 +353,34 @@
     return super.windowProc (hwnd, msg, wParam, lParam);
 }
 
-override LRESULT WM_IME_COMPOSITION (int wParam, int lParam) {
-    LRESULT result  = super.WM_IME_COMPOSITION (wParam, lParam);
+override LRESULT WM_CHAR (int wParam, int lParam) {
+    LRESULT result = super.WM_CHAR (wParam, lParam);
+    if (result !is null) return result;
+    if (caret !is null) {
+        switch (wParam) {
+            case DWT.DEL:
+            case DWT.BS:
+            case DWT.ESC:
+                break;
+            default: {
+                if (OS.GetKeyState (OS.VK_CONTROL) >= 0) {
+                    int value;
+                    if (OS.SystemParametersInfo (OS.SPI_GETMOUSEVANISH, 0, &value, 0)) {
+                        if (value !is 0) OS.SetCursor (null);
+                    }
+                }
+            }
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_IME_COMPOSITION (int /*long*/ wParam, int /*long*/ lParam) {
+    if (ime !is null) {
+        LRESULT result = ime.WM_IME_COMPOSITION (wParam, lParam);
+        if (result !is null) return result;
+    }
+
     /*
     * Bug in Windows.  On Korean Windows XP, the IME window
     * for the Korean Input System (MS-IME 2002) always opens
@@ -339,7 +409,23 @@
             }
         }
     }
-    return result;
+    return super.WM_IME_COMPOSITION (wParam, lParam);
+}
+
+override LRESULT WM_IME_COMPOSITION_START (int /*long*/ wParam, int /*long*/ lParam) {
+    if (ime !is null) {
+        LRESULT result = ime.WM_IME_COMPOSITION_START (wParam, lParam);
+        if (result !is null) return result;
+    }
+    return super.WM_IME_COMPOSITION_START (wParam, lParam);
+}
+
+override LRESULT WM_IME_ENDCOMPOSITION (int /*long*/ wParam, int /*long*/ lParam) {
+    if (ime !is null) {
+        LRESULT result = ime.WM_IME_ENDCOMPOSITION (wParam, lParam);
+        if (result !is null) return result;
+    }
+    return super.WM_IME_ENDCOMPOSITION (wParam, lParam);
 }
 
 override LRESULT WM_INPUTLANGCHANGE (int wParam, int lParam) {
@@ -352,11 +438,23 @@
 }
 
 override LRESULT WM_KILLFOCUS (int wParam, int lParam) {
+    if (ime !is null) {
+        LRESULT result = ime.WM_KILLFOCUS (wParam, lParam);
+        if (result !is null) return result;
+    }
     LRESULT result  = super.WM_KILLFOCUS (wParam, lParam);
     if (caret !is null) caret.killFocus ();
     return result;
 }
 
+override LRESULT WM_LBUTTONDOWN (int /*long*/ wParam, int /*long*/ lParam) {
+    if (ime !is null) {
+        LRESULT result = ime.WM_LBUTTONDOWN (wParam, lParam);
+        if (result !is null) return result;
+    }
+    return super.WM_LBUTTONDOWN (wParam, lParam);
+}
+
 override LRESULT WM_SETFOCUS (int wParam, int lParam) {
     LRESULT result  = super.WM_SETFOCUS (wParam, lParam);
     if (caret !is null) caret.setFocus ();
@@ -371,7 +469,7 @@
 
 override LRESULT WM_WINDOWPOSCHANGED (int wParam, int lParam) {
     LRESULT result  = super.WM_WINDOWPOSCHANGED (wParam, lParam);
-    if (result !is null) return result;
+    //if (result !is null) return result;
     /*
     * Bug in Windows.  When a window with style WS_EX_LAYOUTRTL
     * that contains a caret is resized, Windows does not move the
--- a/dwt/widgets/Caret.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/Caret.d	Sat May 17 17:34:28 2008 +0200
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -24,6 +24,7 @@
 
 import dwt.widgets.Widget;
 import dwt.widgets.Canvas;
+import dwt.widgets.IME;
 
 import dwt.dwthelper.utils;
 
@@ -122,6 +123,13 @@
     if (image !is null) {
         Rectangle rect = image.getBounds ();
         return new Rectangle (x, y, rect.width, rect.height);
+    } else {
+        if (!OS.IsWinCE && width is 0) {
+            int buffer;
+            if (OS.SystemParametersInfo (OS.SPI_GETCARETWIDTH, 0, &buffer, 0)) {
+                return new Rectangle (x, y, buffer, height);
+            }
+        }
     }
     return new Rectangle (x, y, width, height);
 }
@@ -206,6 +214,13 @@
     if (image !is null) {
         Rectangle rect = image.getBounds ();
         return new Point (rect.width, rect.height);
+    } else {
+        if (!OS.IsWinCE && width is 0) {
+            int buffer;
+            if (OS.SystemParametersInfo (OS.SPI_GETCARETWIDTH, 0, &buffer, 0)) {
+                return new Point (buffer, height);
+            }
+        }
     }
     return new Point (width, height);
 }
@@ -275,18 +290,29 @@
     POINT ptCurrentPos;
     if (!OS.GetCaretPos (&ptCurrentPos)) return;
     auto hwnd = parent.handle;
-    RECT rect;
-    OS.GetClientRect (hwnd, &rect);
-    COMPOSITIONFORM lpCompForm;
-    lpCompForm.dwStyle = OS.CFS_RECT;
-    lpCompForm.ptCurrentPos.x = ptCurrentPos.x;
-    lpCompForm.ptCurrentPos.y = ptCurrentPos.y;
-    lpCompForm.rcArea.left = rect.left;
-    lpCompForm.rcArea.right = rect.right;
-    lpCompForm.rcArea.top = rect.top;
-    lpCompForm.rcArea.bottom = rect.bottom;
     auto hIMC = OS.ImmGetContext (hwnd);
-    OS.ImmSetCompositionWindow (hIMC, &lpCompForm);
+    IME ime = parent.getIME ();
+    if (ime !is null && ime.isInlineEnabled ()) {
+        Point size = getSize ();
+        CANDIDATEFORM lpCandidate;
+        lpCandidate.dwStyle = OS.CFS_EXCLUDE;
+        lpCandidate.ptCurrentPos = ptCurrentPos;
+        //lpCandidate.rcArea = new RECT ();
+        OS.SetRect (&lpCandidate.rcArea, ptCurrentPos.x, ptCurrentPos.y, ptCurrentPos.x + size.x, ptCurrentPos.y + size.y);
+        OS.ImmSetCandidateWindow (hIMC, &lpCandidate);
+    } else {
+        RECT rect;
+        OS.GetClientRect (hwnd, &rect);
+        COMPOSITIONFORM lpCompForm;
+        lpCompForm.dwStyle = OS.CFS_RECT;
+        lpCompForm.ptCurrentPos.x = ptCurrentPos.x;
+        lpCompForm.ptCurrentPos.y = ptCurrentPos.y;
+        lpCompForm.rcArea.left = rect.left;
+        lpCompForm.rcArea.right = rect.right;
+        lpCompForm.rcArea.top = rect.top;
+        lpCompForm.rcArea.bottom = rect.bottom;
+        OS.ImmSetCompositionWindow (hIMC, &lpCompForm);
+    }
     OS.ImmReleaseContext (hwnd, hIMC);
 }
 
@@ -308,6 +334,13 @@
     auto hwnd = parent.handle;
     OS.DestroyCaret ();
     auto hBitmap = image !is null ? image.handle : null;
+    int width = this.width;
+    if (!OS.IsWinCE && image is null && width is 0) {
+        int buffer;
+        if (OS.SystemParametersInfo (OS.SPI_GETCARETWIDTH, 0, &buffer, 0)) {
+            width = buffer;
+        }
+    }
     OS.CreateCaret (hwnd, hBitmap, width, height);
     OS.SetCaretPos (x, y);
     OS.ShowCaret (hwnd);
@@ -345,8 +378,10 @@
     bool samePosition = this.x is x && this.y is y;
     bool sameExtent = this.width is width && this.height is height;
     if (samePosition && sameExtent) return;
-    this.x = x;  this.y = y;
-    this.width = width;  this.height = height;
+    this.x = x;
+    this.y = y;
+    this.width = width;
+    this.height = height;
     if (sameExtent) {
         moved = true;
         if (isVisible_ && hasFocus ()) move ();
@@ -378,6 +413,13 @@
     auto hwnd = parent.handle;
     HBITMAP hBitmap;
     if (image !is null) hBitmap = image.handle;
+    int width = this.width;
+    if (!OS.IsWinCE && image is null && width is 0) {
+        int buffer;
+        if (OS.SystemParametersInfo (OS.SPI_GETCARETWIDTH, 0, &buffer, 0)) {
+            width = buffer;
+        }
+    }
     OS.CreateCaret (hwnd, hBitmap, width, height);
     move ();
     setIMEFont ();
--- a/dwt/widgets/ColorDialog.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/ColorDialog.d	Sat May 17 17:34:28 2008 +0200
@@ -65,7 +65,7 @@
  * @see Widget#getStyle
  */
 public this (Shell parent) {
-    this (parent, DWT.PRIMARY_MODAL);
+    this (parent, DWT.APPLICATION_MODAL);
 }
 
 /**
@@ -97,7 +97,7 @@
  * @see Widget#getStyle
  */
 public this (Shell parent, int style) {
-    super (parent, style);
+    super (parent, checkStyle (parent, style));
     checkSubclass ();
 }
 
@@ -165,6 +165,35 @@
 
     /* Get the owner HWND for the dialog */
     auto hwndOwner = parent.handle;
+    auto hwndParent = parent.handle;
+
+    /*
+    * Feature in Windows.  There is no API to set the orientation of a
+    * color dialog.  It is always inherited from the parent.  The fix is
+    * to create a hidden parent and set the orientation in the hidden
+    * parent for the dialog to inherit.
+    */
+    bool enabled = false;
+    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION(4, 10)) {
+        int dialogOrientation = style & (DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT);
+        int parentOrientation = parent.style & (DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT);
+        if (dialogOrientation !is parentOrientation) {
+            int exStyle = OS.WS_EX_NOINHERITLAYOUT;
+            if (dialogOrientation is DWT.RIGHT_TO_LEFT) exStyle |= OS.WS_EX_LAYOUTRTL;
+            hwndOwner = OS.CreateWindowEx (
+                exStyle,
+                Shell.DialogClass.ptr,
+                null,
+                0,
+                OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
+                hwndParent,
+                null,
+                OS.GetModuleHandle (null),
+                null);
+            enabled = OS.IsWindowEnabled (hwndParent) !is 0;
+            if (enabled) OS.EnableWindow (hwndParent, false);
+        }
+    }
 
     /* Create the CCHookProc */
     //Callback callback = new Callback (this, "CCHookProc", 4); //$NON-NLS-1$
@@ -196,10 +225,10 @@
     }
 
     /* Make the parent shell be temporary modal */
-    Shell oldModal = null;
+    Dialog oldModal = null;
     if ((style & (DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL)) !is 0) {
-        oldModal = display.getModalDialogShell ();
-        display.setModalDialogShell (parent);
+        oldModal = display.getModalDialog ();
+        display.setModalDialog (this);
     }
 
     /* Open the dialog */
@@ -212,7 +241,7 @@
 
     /* Clear the temporary dialog modal parent */
     if ((style & (DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL)) !is 0) {
-        display.setModalDialogShell (oldModal);
+        display.setModalDialog (oldModal);
     }
 
     if (success) {
@@ -234,6 +263,13 @@
     */
 //  if (lpCustColors !is 0) OS.HeapFree (hHeap, 0, lpCustColors);
 
+    /* Destroy the BIDI orientation window */
+    if (hwndParent !is hwndOwner) {
+        if (enabled) OS.EnableWindow (hwndParent, true);
+        OS.SetActiveWindow (hwndParent);
+        OS.DestroyWindow (hwndOwner);
+    }
+
     /*
     * This code is intentionally commented.  On some
     * platforms, the owner window is repainted right
@@ -242,6 +278,7 @@
     */
 //  if (hwndOwner !is 0) OS.UpdateWindow (hwndOwner);
 
+    display = null;
     if (!success) return null;
     return rgb;
 }
--- a/dwt/widgets/Combo.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/Combo.d	Sat May 17 17:34:28 2008 +0200
@@ -78,7 +78,7 @@
     alias Composite.setToolTipText setToolTipText;
 
     private static Combo pThis;
-    bool noSelection, ignoreDefaultSelection, ignoreCharacter, ignoreModify;
+    bool noSelection, ignoreDefaultSelection, ignoreCharacter, ignoreModify, ignoreResize;
     HHOOK cbtHook;
     int scrollWidth, visibleCount = 5;
 
@@ -321,6 +321,14 @@
 override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) {
     if (handle is null) return 0;
     if (hwnd is handle) {
+        switch (msg) {
+            case OS.WM_SIZE: {
+                ignoreResize = true;
+                int /*long*/ result = OS.CallWindowProc (ComboProc, hwnd, msg, wParam, lParam);
+                ignoreResize = false;
+                return result;
+            }
+        }
         return OS.CallWindowProc( ComboProc, hwnd, msg, wParam, lParam);
     }
     auto hwndText = OS.GetDlgItem (handle, CBID_EDIT);
@@ -462,8 +470,8 @@
     } else {
         auto hwndText = OS.GetDlgItem (handle, CBID_EDIT);
         if (hwndText !is null) {
-            int margins = OS.SendMessage (hwndText, OS.EM_GETMARGINS, 0, 0);
-            int marginWidth = (margins & 0xFFFF) + ((margins >> 16) & 0xFFFF);
+            int /*long*/ margins = OS.SendMessage (hwndText, OS.EM_GETMARGINS, 0, 0);
+            int marginWidth = OS.LOWORD (margins) + OS.HIWORD (margins);
             width += marginWidth + 3;
         }
     }
@@ -537,11 +545,11 @@
     /* Get the text and list window procs */
     auto hwndText = OS.GetDlgItem (handle, CBID_EDIT);
     if (hwndText !is null && EditProc is null) {
-        EditProc = cast(WNDPROC) OS.GetWindowLong (hwndText, OS.GWL_WNDPROC);
+        EditProc = cast(WNDPROC) OS.GetWindowLongPtr (hwndText, OS.GWLP_WNDPROC);
     }
     auto hwndList = OS.GetDlgItem (handle, CBID_LIST);
     if (hwndList !is null && ListProc is null) {
-        ListProc = cast(WNDPROC) OS.GetWindowLong (hwndList, OS.GWL_WNDPROC);
+        ListProc = cast(WNDPROC) OS.GetWindowLongPtr (hwndList, OS.GWLP_WNDPROC);
     }
 
     /*
@@ -638,8 +646,8 @@
             int start, end;
             OS.SendMessage (handle, OS.CB_GETEDITSEL, &start, &end);
             if (start !is end ) {
-                int lParam = (x & 0xFFFF) | ((y << 16) & 0xFFFF0000);
-                int position = OS.SendMessage (hwndText, OS.EM_CHARFROMPOS, 0, lParam) & 0xFFFF;
+                int /*long*/ lParam = OS.MAKELPARAM (x, y);
+                int position = OS.LOWORD (OS.SendMessage (hwndText, OS.EM_CHARFROMPOS, 0, lParam));
                 if (start <= position && position < end ) {
                     if (super.dragDetect (hwnd, x, y, filter, detect, consume)) {
                         if (consume !is null) consume [0] = true;
@@ -759,9 +767,9 @@
  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
  * </ul>
  *
- * @since 3.3
+ * @since 3.4
  */
-/*public*/ bool getListVisible () {
+public bool getListVisible () {
     checkWidget ();
     if ((style & DWT.DROP_DOWN) !is 0) {
         return OS.SendMessage (handle, OS.CB_GETDROPPEDSTATE, 0, 0) !is 0;
@@ -774,6 +782,29 @@
 }
 
 /**
+ * Marks the receiver's list as visible if the argument is <code>true</code>,
+ * and marks it invisible otherwise.
+ * <p>
+ * If one of the receiver's ancestors is not visible or some
+ * other condition makes the receiver not visible, marking
+ * it visible may not actually cause it to be displayed.
+ * </p>
+ *
+ * @param visible the new visibility state
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @since 3.4
+ */
+public void setListVisible (bool visible) {
+    checkWidget ();
+    OS.SendMessage (handle, OS.CB_SHOWDROPDOWN, visible ? 1 : 0, 0);
+}
+
+/**
  * Returns the orientation of the receiver.
  *
  * @return the orientation style
@@ -1570,29 +1601,6 @@
 }
 
 /**
- * Marks the receiver's list as visible if the argument is <code>true</code>,
- * and marks it invisible otherwise.
- * <p>
- * If one of the receiver's ancestors is not visible or some
- * other condition makes the receiver not visible, marking
- * it visible may not actually cause it to be displayed.
- * </p>
- *
- * @param visible the new visibility state
- *
- * @exception DWTException <ul>
- *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
- *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
- * </ul>
- *
- * @since 3.3
- */
-/*public*/ void setListVisible (bool visible) {
-    checkWidget ();
-    OS.SendMessage (handle, OS.CB_SHOWDROPDOWN, visible ? 1 : 0, 0);
-}
-
-/**
  * Sets the orientation of the receiver, which must be one
  * of the constants <code>DWT.LEFT_TO_RIGHT</code> or <code>DWT.RIGHT_TO_LEFT</code>.
  * <p>
@@ -1778,7 +1786,7 @@
         start = wcsToMbcsPos (start);
         end = wcsToMbcsPos (end);
     }
-    int bits = (start & 0xFFFF) | ((end << 16) & 0xFFFF0000);
+    int /*long*/ bits = OS.MAKELPARAM (start, end);
     OS.SendMessage (handle, OS.CB_SETEDITSEL, 0, bits);
 }
 
@@ -1814,7 +1822,7 @@
     int limit = LIMIT;
     auto hwndText = OS.GetDlgItem (handle, CBID_EDIT);
     if (hwndText !is null) {
-        limit = OS.SendMessage (hwndText, OS.EM_GETLIMITTEXT, 0, 0);
+        limit = OS.SendMessage (hwndText, OS.EM_GETLIMITTEXT, 0, 0) & 0x7FFFFFFF;
     }
     if (string.length  > limit) string = string.substring (0, limit);
     TCHAR* buffer = StrToTCHARz( string );
@@ -1893,11 +1901,11 @@
     auto newProc = display.windowProc;
     auto hwndText = OS.GetDlgItem (handle, CBID_EDIT);
     if (hwndText !is null) {
-        OS.SetWindowLong (hwndText, OS.GWL_WNDPROC, newProc);
+        OS.SetWindowLongPtr (hwndText, OS.GWLP_WNDPROC, newProc);
     }
     auto hwndList = OS.GetDlgItem (handle, CBID_LIST);
     if (hwndList !is null) {
-        OS.SetWindowLong (hwndList, OS.GWL_WNDPROC, newProc);
+        OS.SetWindowLongPtr (hwndList, OS.GWLP_WNDPROC, newProc);
     }
 }
 
@@ -1907,7 +1915,7 @@
     * to select an item in the list and escape to close
     * the combo box.
     */
-    switch (msg.wParam) {
+    switch ((msg.wParam)) {
         case OS.VK_RETURN:
         case OS.VK_ESCAPE:
             if ((style & DWT.DROP_DOWN) !is 0) {
@@ -1944,11 +1952,11 @@
     super.unsubclass ();
     auto hwndText = OS.GetDlgItem (handle, CBID_EDIT);
     if (hwndText !is null && EditProc !is null) {
-        OS.SetWindowLong (hwndText, OS.GWL_WNDPROC, cast(int) EditProc);
+        OS.SetWindowLongPtr (hwndText, OS.GWLP_WNDPROC, cast(LONG_PTR)EditProc);
     }
     auto hwndList = OS.GetDlgItem (handle, CBID_LIST);
     if (hwndList !is null && ListProc !is null) {
-        OS.SetWindowLong (hwndList, OS.GWL_WNDPROC, cast(int) ListProc);
+        OS.SetWindowLongPtr (hwndList, OS.GWLP_WNDPROC, cast(LONG_PTR)ListProc);
     }
 }
 
@@ -2107,7 +2115,7 @@
 }
 
 override LRESULT WM_GETDLGCODE (int wParam, int lParam) {
-    int code = callWindowProc (handle, OS.WM_GETDLGCODE, wParam, lParam);
+    int /*long*/ code = callWindowProc (handle, OS.WM_GETDLGCODE, wParam, lParam);
     return new LRESULT (code | OS.DLGC_WANTARROWS);
 }
 
@@ -2164,6 +2172,16 @@
 
 override LRESULT WM_SIZE (int wParam, int lParam) {
     /*
+    * Feature in Windows.  When a combo box is resized,
+    * the size of the drop down rectangle is specified
+    * using the height and then the combo box resizes
+    * to be the height of the text field.  This causes
+    * two WM_SIZE messages to be sent and two DWT.Resize
+    * events to be issued.  The fix is to ignore the
+    * second resize.
+    */
+    if (ignoreResize) return null;
+    /*
     * Bug in Windows.  If the combo box has the CBS_SIMPLE style,
     * the list portion of the combo box is not redrawn when the
     * combo box is resized.  The fix is to force a redraw when
@@ -2221,7 +2239,7 @@
         if (isDisposed ()) return result;
         if (buffer !is null) {
             OS.SetWindowText (handle, buffer.ptr);
-            int bits = (start & 0xFFFF) | ((end << 16) & 0xFFFF0000);
+            int /*long*/ bits = OS.MAKELPARAM (start, end);
             OS.SendMessage (handle, OS.CB_SETEDITSEL, 0, bits);
             if (redraw) setRedraw (true);
         }
@@ -2236,6 +2254,56 @@
     return result;
 }
 
+override LRESULT WM_WINDOWPOSCHANGING (int /*long*/ wParam, int /*long*/ lParam) {
+    LRESULT result = super.WM_WINDOWPOSCHANGING (wParam, lParam);
+    if (result !is null) return result;
+    /*
+    * Feature in Windows.  When a combo box is resized,
+    * the size of the drop down rectangle is specified
+    * using the height and then the combo box resizes
+    * to be the height of the text field.  This causes
+    * sibling windows that intersect with the original
+    * bounds to redrawn.  The fix is to stop the redraw
+    * using SWP_NOREDRAW and then damage the combo box
+    * text field and the area in the parent where the
+    * combo box used to be.
+    */
+    if (OS.IsWinCE) return result;
+    if (drawCount !is 0) return result;
+    if (!OS.IsWindowVisible (handle)) return result;
+    if (ignoreResize) {
+        WINDOWPOS* lpwp = cast(WINDOWPOS*)lParam;
+        if ((lpwp.flags & OS.SWP_NOSIZE) is 0) {
+            lpwp.flags |= OS.SWP_NOREDRAW;
+            OS.InvalidateRect (handle, null, true);
+            RECT rect;
+            OS.GetWindowRect (handle, &rect);
+            int width = rect.right - rect.left;
+            int height = rect.bottom - rect.top;
+            if (width !is 0 && height !is 0) {
+                auto hwndParent = parent.handle;
+                auto hwndChild = OS.GetWindow (hwndParent, OS.GW_CHILD);
+                OS.MapWindowPoints (null, hwndParent, cast(POINT*)&rect, 2);
+                auto rgn1 = OS.CreateRectRgn (rect.left, rect.top, rect.right, rect.bottom);
+                while (hwndChild !is null) {
+                    if (hwndChild !is handle) {
+                        OS.GetWindowRect (hwndChild, &rect);
+                        OS.MapWindowPoints (null, hwndParent, cast(POINT*)&rect, 2);
+                        auto rgn2 = OS.CreateRectRgn (rect.left, rect.top, rect.right, rect.bottom);
+                        OS.CombineRgn (rgn1, rgn1, rgn2, OS.RGN_DIFF);
+                        OS.DeleteObject (rgn2);
+                    }
+                    hwndChild = OS.GetWindow (hwndChild, OS.GW_HWNDNEXT);
+                }
+                int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE;
+                OS.RedrawWindow (hwndParent, null, rgn1, flags);
+                OS.DeleteObject (rgn1);
+            }
+        }
+    }
+    return result;
+}
+
 override LRESULT wmChar (HWND hwnd, int wParam, int lParam) {
     if (ignoreCharacter) return null;
     LRESULT result = super.wmChar (hwnd, wParam, lParam);
@@ -2345,7 +2413,7 @@
 }
 
 override LRESULT wmCommandChild (int wParam, int lParam) {
-    int code = wParam >> 16;
+    int code = OS.HIWORD (wParam);
     switch (code) {
         case OS.CBN_EDITCHANGE:
             if (ignoreModify) break;
@@ -2429,7 +2497,7 @@
     * them to the application.
     */
     ignoreCharacter = true;
-    int result = callWindowProc (hwnd, OS.WM_IME_CHAR, wParam, lParam);
+    int /*long*/ result = callWindowProc (hwnd, OS.WM_IME_CHAR, wParam, lParam);
     MSG msg;
     int flags = OS.PM_REMOVE | OS.PM_NOYIELD | OS.PM_QS_INPUT | OS.PM_QS_POSTMESSAGE;
     while (OS.PeekMessage (&msg, hwnd, OS.WM_CHAR, OS.WM_CHAR, flags)) {
@@ -2472,7 +2540,7 @@
     if (result !is null) return result;
     if ((style & DWT.READ_ONLY) is 0) {
         if (wParam is OS.VK_DOWN) {
-            int code = callWindowProc (hwnd, OS.WM_SYSKEYDOWN, wParam, lParam);
+            int /*long*/ code = callWindowProc (hwnd, OS.WM_SYSKEYDOWN, wParam, lParam);
             int newSelection = OS.SendMessage (handle, OS.CB_GETCURSEL, 0, 0);
             if (oldSelection !is newSelection) {
                 sendEvent (DWT.Modify);
--- a/dwt/widgets/Composite.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/Composite.d	Sat May 17 17:34:28 2008 +0200
@@ -31,6 +31,7 @@
 import dwt.widgets.Event;
 import dwt.widgets.ToolTip;
 import dwt.widgets.Display;
+import dwt.widgets.Widget;
 
 import dwt.dwthelper.System;
 import dwt.dwthelper.utils;
@@ -67,11 +68,11 @@
 
 public class Composite : Scrollable {
 
+    alias Scrollable.setBounds setBounds;
     alias Scrollable.computeSize computeSize;
     alias Scrollable.translateMnemonic translateMnemonic;
 
     Layout layout_;
-    HFONT font;
     WINDOWPOS* [] lpwp;
     Control [] tabList;
     int layoutCount, backgroundMode;
@@ -211,6 +212,17 @@
     }
 }
 
+void checkComposited () {
+    if ((state & CANVAS) !is 0) {
+        if ((style & DWT.TRANSPARENT) !is 0) {
+            auto hwndParent = parent.handle;
+            int bits = OS.GetWindowLong (hwndParent, OS.GWL_EXSTYLE);
+            bits |= OS.WS_EX_COMPOSITED;
+            OS.SetWindowLong (hwndParent, OS.GWL_EXSTYLE, bits);
+        }
+    }
+}
+
 override protected void checkSubclass () {
     /* Do nothing - Subclassing is allowed */
 }
@@ -254,12 +266,75 @@
     return new Point (trim.width, trim.height);
 }
 
+/**
+ * Copies a rectangular area of the receiver at the specified
+ * position using the gc.
+ *
+ * @param gc the gc where the rectangle is to be filled
+ * @param x the x coordinate of the rectangle to be filled
+ * @param y the y coordinate of the rectangle to be filled
+ * @param width the width of the rectangle to be filled
+ * @param height the height of the rectangle to be filled
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the gc is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the gc has been disposed</li>
+ * </ul>
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @since 3.4
+ */
+/*public*/ void copyArea (GC gc, int x, int y, int width, int height) {
+    checkWidget ();
+    if (gc is null) error (DWT.ERROR_NULL_ARGUMENT);
+    if (gc.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT);
+
+    //XP only, no GDI+
+    //#define PW_CLIENTONLY 0x00000001
+    //DCOrg() wrong
+    //topHandle wrong for Tree?
+    auto hDC = gc.handle;
+    int nSavedDC = OS.SaveDC (hDC);
+    OS.IntersectClipRect (hDC, 0, 0, width, height);
+
+    //WRONG PARENT
+    POINT lpPoint;
+    auto hwndParent = OS.GetParent (handle);
+    OS.MapWindowPoints (handle, hwndParent, &lpPoint, 1);
+    RECT rect;
+    OS.GetWindowRect (handle, &rect);
+    POINT lpPoint1, lpPoint2;
+    x = x + (lpPoint.x - rect.left);
+    y = y + (lpPoint.y - rect.top);
+    OS.SetWindowOrgEx (hDC, x, y, &lpPoint1);
+    OS.SetBrushOrgEx (hDC, x, y, &lpPoint2);
+    int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+    if ((bits & OS.WS_VISIBLE) is 0) {
+        OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+    }
+    //NECESSARY?
+    OS.RedrawWindow (handle, null, null, OS.RDW_UPDATENOW | OS.RDW_ALLCHILDREN);
+    OS.PrintWindow (handle, hDC, 0);//0x00000001);
+    if ((bits & OS.WS_VISIBLE) is 0) {
+        OS.DefWindowProc(handle, OS.WM_SETREDRAW, 0, 0);
+    }
+    OS.RestoreDC (hDC, nSavedDC);
+}
+
 override void createHandle () {
     super.createHandle ();
     state |= CANVAS;
     if ((style & (DWT.H_SCROLL | DWT.V_SCROLL)) is 0) {
         state |= THEME_BACKGROUND;
     }
+    if ((style & DWT.TRANSPARENT) !is 0) {
+        int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
+        bits |= OS.WS_EX_TRANSPARENT;
+        OS.SetWindowLong (handle, OS.GWL_EXSTYLE, bits);
+    }
 }
 
 Composite findDeferredControl () {
@@ -677,6 +752,26 @@
     return true;
 }
 
+void releaseParent () {
+    super.releaseParent ();
+    if ((state & CANVAS) !is 0) {
+        if ((style & DWT.TRANSPARENT) !is 0) {
+            auto hwndParent = parent.handle;
+            auto hwndChild = OS.GetWindow (hwndParent, OS.GW_CHILD);
+            while (hwndChild !is null) {
+                if (hwndChild !is handle) {
+                    int bits = OS.GetWindowLong (hwndParent, OS.GWL_EXSTYLE);
+                    if ((bits & OS.WS_EX_TRANSPARENT) !is 0) return;
+                }
+                hwndChild = OS.GetWindow (hwndChild, OS.GW_HWNDNEXT);
+            }
+            int bits = OS.GetWindowLong (hwndParent, OS.GWL_EXSTYLE);
+            bits &= ~OS.WS_EX_COMPOSITED;
+            OS.SetWindowLong (hwndParent, OS.GWL_EXSTYLE, bits);
+        }
+    }
+}
+
 override void releaseChildren (bool destroy) {
     Control [] children = _getChildren ();
     for (int i=0; i<children.length; i++) {
@@ -776,7 +871,7 @@
 
 void sendResize () {
     setResizeChildren (false);
-    sendEvent (DWT.Resize);
+    super.sendResize ();
     if (isDisposed ()) return;
     if (layout_ !is null) {
         markLayout (false, false);
@@ -811,6 +906,24 @@
     }
 }
 
+void setBounds (int x, int y, int width, int height, int flags, bool defer) {
+    if (display.resizeCount > Display.RESIZE_LIMIT) {
+        defer = false;
+    }
+    if (!defer && (state & CANVAS) !is 0) {
+        state &= ~RESIZE_OCCURRED | MOVE_OCCURRED;
+        state |= RESIZE_DEFERRED | MOVE_DEFERRED;
+    }
+    super.setBounds (x, y, width, height, flags, defer);
+    if (!defer && (state & CANVAS) !is 0) {
+        bool wasMoved = (state & MOVE_OCCURRED) !is 0;
+        bool wasResized = (state & RESIZE_OCCURRED) !is 0;
+        state &= ~(RESIZE_DEFERRED | MOVE_DEFERRED);
+        if (wasMoved && !isDisposed ()) sendMove ();
+        if (wasResized && !isDisposed ()) sendResize ();
+    }
+}
+
 override bool setFixedFocus () {
     checkWidget ();
     Control [] children = _getChildren ();
@@ -923,6 +1036,9 @@
     if (resize) {
         resizeChildren ();
     } else {
+        if (display.resizeCount > Display.RESIZE_LIMIT) {
+            return;
+        }
         int count = getChildrenCount ();
         if (count > 1 && lpwp is null) {
             lpwp = new WINDOWPOS* [count];
@@ -945,7 +1061,9 @@
     }
     for (int i=0; i<children.length; i++) {
         Control child = children [i];
-        if (child.isTabItem () && child.setTabItemFocus ()) return true;
+        if (child.isTabItem () && !child.isTabGroup () && child.setTabItemFocus ()) {
+            return true;
+        }
     }
     return false;
 }
@@ -989,7 +1107,10 @@
             case OS.VK_RIGHT:
             case OS.VK_PRIOR:
             case OS.VK_NEXT:
-                OS.SendMessage (msg.hwnd, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0);
+                int uiState = OS.SendMessage (msg.hwnd, OS.WM_QUERYUISTATE, 0, 0);
+                if ((uiState & OS.UISF_HIDEFOCUS) !is 0) {
+                    OS.SendMessage (msg.hwnd, OS.WM_UPDATEUISTATE, OS.MAKEWPARAM (OS.UIS_CLEAR, OS.UISF_HIDEFOCUS), 0);
+                }
                 break;
             default:
         }
@@ -1058,6 +1179,14 @@
     }
 }
 
+void updateUIState () {
+    HWND hwndShell = getShell ().handle;
+    int uiState = OS.SendMessage (hwndShell, OS.WM_QUERYUISTATE, 0, 0);
+    if ((uiState & OS.UISF_HIDEFOCUS) !is 0) {
+        OS.SendMessage (hwndShell, OS.WM_CHANGEUISTATE, OS.MAKEWPARAM (OS.UIS_CLEAR, OS.UISF_HIDEFOCUS), 0);
+    }
+}
+
 override int widgetStyle () {
     /* Force clipping of children by setting WS_CLIPCHILDREN */
     return super.widgetStyle () | OS.WS_CLIPCHILDREN;
@@ -1068,7 +1197,9 @@
     if (result !is null) return result;
     if ((state & CANVAS) !is 0) {
         /* Return zero to indicate that the background was not erased */
-        if ((style & DWT.NO_BACKGROUND) !is 0) return LRESULT.ZERO;
+        if ((style & (DWT.NO_BACKGROUND | DWT.TRANSPARENT)) !is 0) {
+            return LRESULT.ZERO;
+        }
     }
     return result;
 }
@@ -1091,10 +1222,9 @@
 override LRESULT WM_GETFONT (int wParam, int lParam) {
     LRESULT result = super.WM_GETFONT (wParam, lParam);
     if (result !is null) return result;
-    int code = callWindowProc (handle, OS.WM_GETFONT, wParam, lParam);
+    int /*long*/ code = callWindowProc (handle, OS.WM_GETFONT, wParam, lParam);
     if (code !is 0) return new LRESULT (code);
-    if (font is null) font = defaultFont ();
-    return new LRESULT (cast(int) font);
+    return new LRESULT ( cast(int)(font !is null ? font.handle : defaultFont ()));
 }
 
 override LRESULT WM_LBUTTONDOWN (int wParam, int lParam) {
@@ -1110,18 +1240,45 @@
     return result;
 }
 
-override LRESULT WM_NCPAINT (int wParam, int lParam) {
-    LRESULT result = super.WM_NCPAINT (wParam, lParam);
+override LRESULT WM_NCHITTEST (int /*long*/ wParam, int /*long*/ lParam) {
+    LRESULT result = super.WM_NCHITTEST (wParam, lParam);
     if (result !is null) return result;
-    if ((state & CANVAS) !is 0) {
-        result = wmNCPaint (handle, wParam, lParam);
+    /*
+    * Bug in Windows.  For some reason, under circumstances
+    * that are not understood, when one scrolled window is
+    * embedded in another and the outer window scrolls the
+    * inner horizontally by moving the location of the inner
+    * one, the vertical scroll bars of the inner window no
+    * longer function.  Specifically, WM_NCHITTEST returns
+    * HTCLIENT instead of HTVSCROLL.  The fix is to detect
+    * the case where the result of WM_NCHITTEST is HTCLIENT
+    * and the point is not in the client area, and redraw
+    * the trim, which somehow fixes the next WM_NCHITTEST.
+    */
+    if (!OS.IsWinCE && OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+        if ((state & CANVAS)!is 0) {
+            auto code = callWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam);
+            if (code is OS.HTCLIENT) {
+                RECT rect;
+                OS.GetClientRect (handle, &rect);
+                POINT pt;
+                pt.x = OS.GET_X_LPARAM (lParam);
+                pt.y = OS.GET_Y_LPARAM (lParam);
+                OS.MapWindowPoints (null, handle, &pt, 1);
+                if (!OS.PtInRect (&rect, pt)) {
+                    int flags = OS.RDW_FRAME | OS.RDW_INVALIDATE;
+                    OS.RedrawWindow (handle, null, null, flags);
+                }
+            }
+            return new LRESULT (code);
+        }
     }
     return result;
 }
 
 override LRESULT WM_PARENTNOTIFY (int wParam, int lParam) {
     if ((state & CANVAS) !is 0 && (style & DWT.EMBEDDED) !is 0) {
-        if ((wParam & 0xFFFF) is OS.WM_CREATE) {
+        if (OS.LOWORD (wParam) is OS.WM_CREATE) {
             RECT rect;
             OS.GetClientRect (handle, &rect);
             resizeEmbeddedHandle ( cast(HANDLE)lParam, rect.right - rect.left, rect.bottom - rect.top);
@@ -1152,7 +1309,7 @@
         if ((style & DWT.DOUBLE_BUFFERED) !is 0) {
             if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
                 if ((style & (DWT.NO_MERGE_PAINTS | DWT.RIGHT_TO_LEFT)) is 0) {
-                    bufferedPaint = true;
+                    if ((style & DWT.TRANSPARENT) is 0) bufferedPaint = true;
                 }
             }
         }
@@ -1167,17 +1324,12 @@
                 OS.SetRect (&prcTarget, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom);
                 auto hBufferedPaint = OS.BeginBufferedPaint (hDC, &prcTarget, flags, null, &phdc);
                 GCData data = new GCData ();
-                if ((OS.GetLayout (hDC) & OS.LAYOUT_RTL) !is 0) {
-                    data.style = DWT.RIGHT_TO_LEFT | DWT.MIRRORED;
-                } else {
-                    data.style = DWT.LEFT_TO_RIGHT;
-                }
                 data.device = display;
                 data.foreground = getForegroundPixel ();
                 Control control = findBackgroundControl ();
                 if (control is null) control = this;
                 data.background = control.getBackgroundPixel ();
-                data.hFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+                data.font = Font.win32_new(display, cast(HANDLE) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0));
                 data.uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
                 if ((style & DWT.NO_BACKGROUND) !is 0) {
                     /* This code is intentionally commented because it may be slow to copy bits from the screen */
@@ -1195,6 +1347,7 @@
                 event.width = width;
                 event.height = height;
                 sendEvent (DWT.Paint, event);
+                if (data.focusDrawn && !isDisposed ()) updateUIState ();
                 gc.dispose ();
                 OS.EndBufferedPaint (hBufferedPaint, true);
             }
@@ -1209,7 +1362,7 @@
 
             /* Get the system region for the paint HDC */
             HRGN sysRgn;
-            if ((style & (DWT.NO_MERGE_PAINTS | DWT.DOUBLE_BUFFERED)) !is 0) {
+            if ((style & (DWT.DOUBLE_BUFFERED | DWT.TRANSPARENT)) !is 0 || (style & DWT.NO_MERGE_PAINTS) !is 0) {
                 sysRgn = OS.CreateRectRgn (0, 0, 0, 0);
                 if (OS.GetRandomRgn (gc.handle, sysRgn, OS.SYSRGN) is 1) {
                     if (OS.WIN32_VERSION >= OS.VERSION (4, 10)) {
@@ -1236,7 +1389,7 @@
             if (width !is 0 && height !is 0) {
                 GC paintGC = null;
                 Image image = null;
-                if ((style & DWT.DOUBLE_BUFFERED) !is 0) {
+                if ((style & (DWT.DOUBLE_BUFFERED | DWT.TRANSPARENT)) !is 0) {
                     image = new Image (display, width, height);
                     paintGC = gc;
                     gc = new GC (image, paintGC.getStyle() & DWT.RIGHT_TO_LEFT);
@@ -1245,13 +1398,16 @@
                     gc.setForeground (getForeground ());
                     gc.setBackground (getBackground ());
                     gc.setFont (getFont ());
+                    if ((style & DWT.TRANSPARENT) !is 0) {
+                        OS.BitBlt (gc.handle, 0, 0, width, height, paintGC.handle, ps.rcPaint.left, ps.rcPaint.top, OS.SRCCOPY);
+                    }
                     OS.OffsetRgn (sysRgn, -ps.rcPaint.left, -ps.rcPaint.top);
                     OS.SelectClipRgn (gc.handle, sysRgn);
                     OS.OffsetRgn (sysRgn, ps.rcPaint.left, ps.rcPaint.top);
                     OS.SetMetaRgn (gc.handle);
                     OS.SetWindowOrgEx (gc.handle, ps.rcPaint.left, ps.rcPaint.top, null);
                     OS.SetBrushOrgEx (gc.handle, ps.rcPaint.left, ps.rcPaint.top, null);
-                    if ((style & DWT.NO_BACKGROUND) !is 0) {
+                    if ((style & (DWT.NO_BACKGROUND | DWT.TRANSPARENT)) !is 0) {
                         /* This code is intentionally commented because it may be slow to copy bits from the screen */
                         //paintGC.copyArea (image, ps.left, ps.top);
                     } else {
@@ -1271,7 +1427,7 @@
                     for (int i=0; i<count; i++) {
                         int offset = 8 + (i << 2);
                         OS.SetRect (&rect, lpRgnData [offset], lpRgnData [offset + 1], lpRgnData [offset + 2], lpRgnData [offset + 3]);
-                        if ((style & (DWT.DOUBLE_BUFFERED | DWT.NO_BACKGROUND)) is 0) {
+                        if ((style & (DWT.DOUBLE_BUFFERED | DWT.NO_BACKGROUND | DWT.TRANSPARENT)) is 0) {
                             drawBackground (gc.handle, &rect);
                         }
                         event.x = rect.left;
@@ -1282,7 +1438,7 @@
                         sendEvent (DWT.Paint, event);
                     }
                 } else {
-                    if ((style & (DWT.DOUBLE_BUFFERED | DWT.NO_BACKGROUND)) is 0) {
+                    if ((style & (DWT.DOUBLE_BUFFERED | DWT.NO_BACKGROUND | DWT.TRANSPARENT)) is 0) {
                         OS.SetRect (&rect, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom);
                         drawBackground (gc.handle, &rect);
                     }
@@ -1294,7 +1450,11 @@
                 }
                 // widget could be disposed at this point
                 event.gc = null;
-                if ((style & DWT.DOUBLE_BUFFERED) !is 0) {
+                if ((style & (DWT.DOUBLE_BUFFERED | DWT.TRANSPARENT)) !is 0) {
+                    if (!gc.isDisposed ()) {
+                        GCData gcData = gc.getGCData ();
+                        if (gcData.focusDrawn && !isDisposed ()) updateUIState ();
+                    }
                     gc.dispose();
                     if (!isDisposed ()) paintGC.drawImage (image, ps.rcPaint.left, ps.rcPaint.top);
                     image.dispose ();
@@ -1302,13 +1462,14 @@
                 }
             }
             if (sysRgn !is null) OS.DeleteObject (sysRgn);
+            if (data.focusDrawn && !isDisposed ()) updateUIState ();
 
             /* Dispose the paint GC */
             gc.dispose ();
         }
     } else {
         auto hDC = OS.BeginPaint (handle, &ps);
-        if ((style & DWT.NO_BACKGROUND) is 0) {
+        if ((style & (DWT.NO_BACKGROUND | DWT.TRANSPARENT)) is 0) {
             RECT rect;
             OS.SetRect (&rect, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom);
             drawBackground (hDC, &rect);
@@ -1341,7 +1502,7 @@
         auto nSavedDC = OS.SaveDC (cast(HDC)wParam);
         RECT rect;
         OS.GetClientRect (handle, &rect);
-        if ((style & DWT.NO_BACKGROUND) is 0) {
+        if ((style & (DWT.NO_BACKGROUND | DWT.TRANSPARENT)) is 0) {
             drawBackground ( cast(HDC)wParam, &rect);
         }
         if (hooks (DWT.Paint) || filters (DWT.Paint)) {
@@ -1351,7 +1512,7 @@
             Control control = findBackgroundControl ();
             if (control is null) control = this;
             data.background = control.getBackgroundPixel ();
-            data.hFont = cast(HFONT)OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+            data.font = Font.win32_new(display, cast(HANDLE) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0));
             data.uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
             GC gc = GC.win32_new (cast(HDC)wParam, data);
             Event event = new Event ();
@@ -1371,33 +1532,36 @@
 
 override LRESULT WM_SETFONT (int wParam, int lParam) {
     if (lParam !is 0) OS.InvalidateRect (handle, null, true);
-    font = cast(HFONT)wParam;
     return super.WM_SETFONT (wParam, lParam);
 }
 
 override LRESULT WM_SIZE (int wParam, int lParam) {
-
-    /* Begin deferred window positioning */
-    setResizeChildren (false);
+    LRESULT result = null;
+    if ((state & RESIZE_DEFERRED) !is 0) {
+        result = super.WM_SIZE (wParam, lParam);
+    } else {
+        /* Begin deferred window positioning */
+        setResizeChildren (false);
 
-    /* Resize and Layout */
-    LRESULT result = super.WM_SIZE (wParam, lParam);
-    /*
-    * It is possible (but unlikely), that application
-    * code could have disposed the widget in the resize
-    * event.  If this happens, end the processing of the
-    * Windows message by returning the result of the
-    * WM_SIZE message.
-    */
-    if (isDisposed ()) return result;
-    if (layout_ !is null) {
-        markLayout (false, false);
-        updateLayout (false, false);
+        /* Resize and Layout */
+        result = super.WM_SIZE (wParam, lParam);
+        /*
+        * It is possible (but unlikely), that application
+        * code could have disposed the widget in the resize
+        * event.  If this happens, end the processing of the
+        * Windows message by returning the result of the
+        * WM_SIZE message.
+        */
+        if (isDisposed ()) return result;
+        if (layout_ !is null) {
+            markLayout (false, false);
+            updateLayout (false, false);
+        }
+
+        /* End deferred window positioning */
+        setResizeChildren (true);
     }
 
-    /* End deferred window positioning */
-    setResizeChildren (true);
-
     /* Damage the widget to cause a repaint */
     if (OS.IsWindowVisible (handle)) {
         if ((state & CANVAS) !is 0) {
@@ -1414,7 +1578,7 @@
 
     /* Resize the embedded window */
     if ((state & CANVAS) !is 0 && (style & DWT.EMBEDDED) !is 0) {
-        resizeEmbeddedHandle (OS.GetWindow (handle, OS.GW_CHILD), lParam & 0xFFFF, lParam >> 16);
+        resizeEmbeddedHandle (OS.GetWindow (handle, OS.GW_CHILD), OS.LOWORD (lParam), OS.HIWORD (lParam));
     }
     return result;
 }
@@ -1437,6 +1601,8 @@
     /*
     * Check to see if the command is a system command or
     * a user menu item that was added to the system menu.
+    *
+    * NOTE: This is undocumented.
     */
     if ((wParam & 0xF000) is 0) return result;
 
@@ -1454,7 +1620,7 @@
             case OS.SC_VSCROLL:
                 bool showHBar = horizontalBar !is null && horizontalBar.getVisible ();
                 bool showVBar = verticalBar !is null && verticalBar.getVisible ();
-                int code = callWindowProc (handle, OS.WM_SYSCOMMAND, wParam, lParam);
+                int /*long*/ code = callWindowProc (handle, OS.WM_SYSCOMMAND, wParam, lParam);
                 if ((showHBar !is (horizontalBar !is null && horizontalBar.getVisible ())) ||
                     (showVBar !is (verticalBar !is null && verticalBar.getVisible ()))) {
                         int flags = OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_UPDATENOW;
@@ -1472,33 +1638,40 @@
 override LRESULT WM_UPDATEUISTATE (int wParam, int lParam) {
     LRESULT result = super.WM_UPDATEUISTATE (wParam, lParam);
     if (result !is null) return result;
-    if ((state & CANVAS) !is 0) OS.InvalidateRect (handle, null, false);
+    if ((state & CANVAS) !is 0 && hooks (DWT.Paint)) {
+        OS.InvalidateRect (handle, null, true);
+    }
     return result;
 }
 
 LRESULT wmNCPaint (HWND hwnd, int wParam, int lParam) {
-    if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
-        int bits1 = OS.GetWindowLong (hwnd, OS.GWL_EXSTYLE);
-        if ((bits1 & OS.WS_EX_CLIENTEDGE) !is 0) {
-            int code = 0;
-            int bits2 = OS.GetWindowLong (hwnd, OS.GWL_STYLE);
-            if ((bits2 & (OS.WS_HSCROLL | OS.WS_VSCROLL)) !is 0) {
-                code = callWindowProc (hwnd, OS.WM_NCPAINT, wParam, lParam);
+    LRESULT result = super.wmNCPaint (hwnd, wParam, lParam);
+    if (result !is null) return result;
+    auto borderHandle = borderHandle ();
+    if ((state & CANVAS) !is 0 || (hwnd is borderHandle && handle !is borderHandle)) {
+        if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+            int bits1 = OS.GetWindowLong (hwnd, OS.GWL_EXSTYLE);
+            if ((bits1 & OS.WS_EX_CLIENTEDGE) !is 0) {
+                int /*long*/ code = 0;
+                int bits2 = OS.GetWindowLong (hwnd, OS.GWL_STYLE);
+                if ((bits2 & (OS.WS_HSCROLL | OS.WS_VSCROLL)) !is 0) {
+                    code = callWindowProc (hwnd, OS.WM_NCPAINT, wParam, lParam);
+                }
+                auto hDC = OS.GetWindowDC (hwnd);
+                RECT rect;
+                OS.GetWindowRect (hwnd, &rect);
+                rect.right -= rect.left;
+                rect.bottom -= rect.top;
+                rect.left = rect.top = 0;
+                int border = OS.GetSystemMetrics (OS.SM_CXEDGE);
+                OS.ExcludeClipRect (hDC, border, border, rect.right - border, rect.bottom - border);
+                OS.DrawThemeBackground (display.hEditTheme (), hDC, OS.EP_EDITTEXT, OS.ETS_NORMAL, &rect, null);
+                OS.ReleaseDC (hwnd, hDC);
+                return new LRESULT (code);
             }
-            auto hDC = OS.GetWindowDC (hwnd);
-            RECT rect;
-            OS.GetWindowRect (hwnd, &rect);
-            rect.right -= rect.left;
-            rect.bottom -= rect.top;
-            rect.left = rect.top = 0;
-            int border = OS.GetSystemMetrics (OS.SM_CXEDGE);
-            OS.ExcludeClipRect (hDC, border, border, rect.right - border, rect.bottom - border);
-            OS.DrawThemeBackground (display.hEditTheme (), hDC, OS.EP_EDITTEXT, OS.ETS_NORMAL, &rect, null);
-            OS.ReleaseDC (hwnd, hDC);
-            return new LRESULT (code);
         }
     }
-    return null;
+    return result;
 }
 
 override LRESULT wmNotify (NMHDR* hdr, int wParam, int lParam) {
@@ -1568,24 +1741,26 @@
                 if (string !is null) {
                     Shell shell = getShell ();
                     string = Display.withCrLf (string);
-                    int length_ = string.length;
-                    char [] chars = new char [length_ + 1];
-                    string.getChars (0, length_, chars, 0);
-                    chars[$-1] = 0; // d initialize it to 0xFF, we need to make it null terminated
+                    char [] chars = fixMnemonic (string);
 
                     /*
                     * Ensure that the orientation of the tool tip matches
                     * the orientation of the control.
                     */
+                    Widget widget = null;
                     HWND hwnd = cast(HWND)hdr.idFrom;
-                    if (hwnd !is null && ((lpnmtdi.uFlags & OS.TTF_IDISHWND) !is 0)) {
-                        Control control = display.getControl (hwnd);
-                        if (control !is null) {
-                            if ((control.getStyle () & DWT.RIGHT_TO_LEFT) !is 0) {
-                                lpnmtdi.uFlags |= OS.TTF_RTLREADING;
-                            } else {
-                                lpnmtdi.uFlags &= ~OS.TTF_RTLREADING;
-                            }
+                    if ((lpnmtdi.uFlags & OS.TTF_IDISHWND) !is 0) {
+                        widget = display.getControl (hwnd);
+                    } else {
+                        if (hdr.hwndFrom is shell.toolTipHandle || hdr.hwndFrom is shell.balloonTipHandle) {
+                            widget = shell.findToolTip (hdr.idFrom);
+                        }
+                    }
+                    if (widget !is null) {
+                        if ((widget.getStyle () & DWT.RIGHT_TO_LEFT) !is 0) {
+                            lpnmtdi.uFlags |= OS.TTF_RTLREADING;
+                        } else {
+                            lpnmtdi.uFlags &= ~OS.TTF_RTLREADING;
                         }
                     }
 
--- a/dwt/widgets/Control.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/Control.d	Sat May 17 17:34:28 2008 +0200
@@ -37,9 +37,11 @@
 import dwt.graphics.Image;
 import dwt.graphics.Point;
 import dwt.graphics.Rectangle;
+import dwt.graphics.Region;
 import dwt.internal.win32.OS;
 import dwt.widgets.Widget;
 import dwt.widgets.Composite;
+import dwt.widgets.Dialog;
 import dwt.widgets.Event;
 import dwt.widgets.Shell;
 import dwt.widgets.Menu;
@@ -101,6 +103,8 @@
     Object layoutData;
     Accessible accessible;
     Image backgroundImage;
+    Region region;
+    Font font;
     int drawCount, foreground, background;
 
 /**
@@ -516,6 +520,10 @@
     style &= ~DWT.DOUBLE_BUFFERED;
 }
 
+void checkComposited () {
+    /* Do nothing */
+}
+
 bool checkHandle (HWND hwnd) {
     return hwnd is handle;
 }
@@ -648,7 +656,7 @@
     if (handle is null) error (DWT.ERROR_NO_HANDLES);
     int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
     if ((bits & OS.WS_CHILD) !is 0) {
-        OS.SetWindowLong (handle, OS.GWL_ID, cast(int)handle);
+        OS.SetWindowLongPtr (handle, OS.GWLP_ID, cast(LONG_PTR)handle);
     }
     if (OS.IsDBLocale && hwndParent !is null) {
         auto hIMC = OS.ImmGetContext (hwndParent);
@@ -664,6 +672,7 @@
     createHandle ();
     checkBackground ();
     checkBuffered ();
+    checkComposited ();
     register ();
     subclass ();
     setDefaultFont ();
@@ -820,7 +829,7 @@
             if ((stateMask & DWT.BUTTON3) !is 0) wParam |= OS.MK_RBUTTON;
             if ((stateMask & DWT.BUTTON4) !is 0) wParam |= OS.MK_XBUTTON1;
             if ((stateMask & DWT.BUTTON5) !is 0) wParam |= OS.MK_XBUTTON2;
-            int lParam = (x & 0xFFFF) | ((y << 16) & 0xFFFF0000);
+            int /*long*/ lParam = OS.MAKELPARAM (x, y);
             OS.SendMessage (handle, OS.WM_LBUTTONUP, wParam, lParam);
         }
         return false;
@@ -1246,6 +1255,7 @@
  */
 public Font getFont () {
     checkWidget ();
+    if (font !is null) return font;
     auto hFont = cast(HFONT)OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
     if (hFont is null) hFont = defaultFont ();
     return Font.win32_new (display, hFont);
@@ -1392,6 +1402,25 @@
 }
 
 /**
+ * Returns the region that defines the shape of the control,
+ * or null if the control has the default shape.
+ *
+ * @return the region that defines the shape of the shell (or null)
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @since 3.4
+ *
+ */
+public Region getRegion () {
+    checkWidget ();
+    return region;
+}
+
+/**
  * Returns the receiver's shell. For all controls other than
  * shells, this simply returns the control's nearest ancestor
  * shell. Shells return themselves, even if they are children
@@ -1547,7 +1576,7 @@
         if (control is null) control = this;
         auto background = control.getBackgroundPixel ();
         if (background !is OS.GetBkColor (hDC)) data.background = background;
-        data.hFont = cast(HFONT) OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0);
+        data.font = font !is null ? font : Font.win32_new (display, cast(HFONT)OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0));
         data.uiState = OS.SendMessage (hwnd, OS.WM_QUERYUISTATE, 0, 0);
     }
     return hDC;
@@ -1580,9 +1609,12 @@
 }
 
 bool isActive () {
-    Shell dialogShell = display.getModalDialogShell ();
-    if (dialogShell !is null && dialogShell !is getShell ()) {
-        return false;
+    Dialog dialog = display.getModalDialog ();
+    if (dialog !is null) {
+        Shell dialogShell = dialog.parent;
+        if (dialogShell !is null && !dialogShell.isDisposed ()) {
+            if (dialogShell !is getShell ()) return false;
+        }
     }
     Shell shell = null;
     Shell [] modalShells = display.modalShells;
@@ -1696,7 +1728,7 @@
     */
 //  if (!OS.IsWindowVisible (handle)) return false;
 //  int flags = OS.DCX_CACHE | OS.DCX_CLIPCHILDREN | OS.DCX_CLIPSIBLINGS;
-//  int hDC = OS.GetDCEx (handle, 0, flags);
+//  int /*long*/ hDC = OS.GetDCEx (handle, 0, flags);
 //  int result = OS.GetClipBox (hDC, new RECT ());
 //  OS.ReleaseDC (handle, hDC);
 //  return result !is OS.NULLREGION;
@@ -1722,7 +1754,7 @@
     }
     int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
     if ((bits & OS.WS_TABSTOP) !is 0) return false;
-    int code = OS.SendMessage (handle, OS.WM_GETDLGCODE, 0, 0);
+    int /*long*/ code = OS.SendMessage (handle, OS.WM_GETDLGCODE, 0, 0);
     if ((code & OS.DLGC_STATIC) !is 0) return false;
     if ((code & OS.DLGC_WANTALLKEYS) !is 0) return false;
     if ((code & OS.DLGC_WANTARROWS) !is 0) return false;
@@ -1936,6 +1968,45 @@
 }
 
 /**
+ * Prints the receiver and all children.
+ *
+ * @param gc the gc where the drawing occurs
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the gc is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the gc has been disposed</li>
+ * </ul>
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @since 3.4
+ */
+public bool print (GC gc) {
+    checkWidget ();
+    if (gc is null) error (DWT.ERROR_NULL_ARGUMENT);
+    if (gc.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT);
+    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 1)) {
+        auto topHandle = topHandle ();
+        int bits = OS.GetWindowLong (topHandle, OS.GWL_STYLE);
+        if ((bits & OS.WS_VISIBLE) is 0) {
+            OS.DefWindowProc (topHandle, OS.WM_SETREDRAW, 1, 0);
+        }
+        printWidget (topHandle, gc.handle);
+        if ((bits & OS.WS_VISIBLE) is 0) {
+            OS.DefWindowProc (topHandle, OS.WM_SETREDRAW, 0, 0);
+        }
+        return true;
+    }
+    return false;
+}
+
+void printWidget (HWND hwnd, HDC hDC) {
+    OS.PrintWindow (hwnd, hDC, 0);
+}
+
+/**
  * Causes the entire bounds of the receiver to be marked
  * as needing to be redrawn. The next time a paint request
  * is processed, the control will be completely painted,
@@ -2070,6 +2141,8 @@
         accessible.internal_dispose_Accessible ();
     }
     accessible = null;
+    region = null;
+    font = null;
 }
 
 /**
@@ -2423,6 +2496,14 @@
     return true;
 }
 
+void sendMove () {
+    sendEvent (DWT.Move);
+}
+
+void sendResize () {
+    sendEvent (DWT.Resize);
+}
+
 void setBackground () {
     Control control = findBackgroundControl ();
     if (control is null) control = this;
@@ -2552,23 +2633,21 @@
 }
 
 void setBounds (int x, int y, int width, int height, int flags, bool defer) {
+    if (findImageControl () !is null) {
+        if (backgroundImage is null) flags |= OS.SWP_NOCOPYBITS;
+    } else {
+        if (OS.GetWindow (handle, OS.GW_CHILD) is null) {
+            if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+                if (findThemeControl () !is null) flags |= OS.SWP_NOCOPYBITS;
+            }
+        }
+    }
     auto topHandle_ = topHandle ();
     if (defer && parent !is null) {
         forceResize ();
-        if (OS.GetWindow (handle, OS.GW_CHILD) is null) {
-            if (findImageControl () !is null) {
-                flags |= OS.SWP_NOCOPYBITS;
-            } else {
-                if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
-                    if (findThemeControl () !is null) flags |= OS.SWP_NOCOPYBITS;
-                }
-            }
-        }
-        WINDOWPOS* [] lpwp = parent.lpwp;
-        if (lpwp is null) {
-            SetWindowPos (topHandle_, null, x, y, width, height, flags);
-        } else {
+        if (parent.lpwp !is null) {
             int index = 0;
+            auto lpwp = parent.lpwp;
             while (index < lpwp.length) {
                 if (lpwp [index] is null) break;
                 index ++;
@@ -2586,10 +2665,10 @@
             wp.cy = height;
             wp.flags = flags;
             lpwp [index] = wp;
+            return;
         }
-    } else {
-        SetWindowPos (topHandle_, null, x, y, width, height, flags);
     }
+    SetWindowPos (topHandle_, null, x, y, width, height, flags);
 }
 
 /**
@@ -2619,7 +2698,8 @@
 /**
  * If the argument is <code>true</code>, causes the receiver to have
  * all mouse events delivered to it until the method is called with
- * <code>false</code> as the argument.
+ * <code>false</code> as the argument.  Note that on some platforms,
+ * a mouse button must currently be down for capture to be assigned.
  *
  * @param capture <code>true</code> to capture the mouse, and <code>false</code> to release it
  *
@@ -2640,7 +2720,7 @@
 }
 
 void setCursor () {
-    int lParam = OS.HTCLIENT | (OS.WM_MOUSEMOVE << 16);
+    int /*long*/ lParam = OS.MAKELPARAM (OS.HTCLIENT, OS.WM_MOUSEMOVE);
     OS.SendMessage (handle, OS.WM_SETCURSOR, handle, lParam);
 }
 
@@ -2668,7 +2748,7 @@
     if (cursor !is null && cursor.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
     this.cursor = cursor;
     static if (OS.IsWinCE) {
-        int hCursor = cursor !is null ? cursor.handle : 0;
+        int /*long*/ hCursor = cursor !is null ? cursor.handle : 0;
         OS.SetCursor (hCursor);
         return;
     }
@@ -2797,6 +2877,7 @@
         if (font.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
         hFont = font.handle;
     }
+    this.font = font;
     if (hFont is null) hFont = defaultFont ();
     OS.SendMessage (handle, OS.WM_SETFONT, hFont, 1);
 }
@@ -3010,6 +3091,36 @@
     }
 }
 
+/**
+ * Sets the shape of the control to the region specified
+ * by the argument.  When the argument is null, the
+ * default shape of the control is restored.
+ *
+ * @param region the region that defines the shape of the control (or null)
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if the region has been disposed</li>
+ * </ul>
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @since 3.4
+ *
+ */
+public void setRegion (Region region) {
+    checkWidget ();
+    if (region !is null && region.isDisposed()) error (DWT.ERROR_INVALID_ARGUMENT);
+    HRGN hRegion;
+    if (region !is null) {
+        hRegion = OS.CreateRectRgn (0, 0, 0, 0);
+        OS.CombineRgn (hRegion, region.handle, hRegion, OS.RGN_OR);
+    }
+    OS.SetWindowRgn (handle, hRegion, true);
+    this.region = region;
+}
+
 bool setSavedFocus () {
     return forceFocus ();
 }
@@ -3164,10 +3275,10 @@
 }
 
 void subclass () {
-    int oldProc = windowProc ();
+    int /*long*/ oldProc = windowProc ();
     int newProc = display.windowProc();
     if (oldProc is newProc) return;
-    OS.SetWindowLong (handle, OS.GWL_WNDPROC, newProc);
+    OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, newProc);
 }
 
 /**
@@ -3281,7 +3392,7 @@
     if (msg.wParam < 0x20) return false;
     auto hwnd = msg.hwnd;
     if (OS.GetKeyState (OS.VK_MENU) >= 0) {
-        int code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0);
+        int /*long*/ code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0);
         if ((code & OS.DLGC_WANTALLKEYS) !is 0) return false;
         if ((code & OS.DLGC_BUTTON) is 0) return false;
     }
@@ -3313,7 +3424,7 @@
         case OS.VK_ESCAPE: {
             all = true;
             lastAscii = 27;
-            int code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0);
+            int /*long*/ code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0);
             if ((code & OS.DLGC_WANTALLKEYS) !is 0) {
                 /*
                 * Use DLGC_HASSETSEL to determine that the control
@@ -3330,7 +3441,7 @@
         case OS.VK_RETURN: {
             all = true;
             lastAscii = '\r';
-            int code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0);
+            int /*long*/ code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0);
             if ((code & OS.DLGC_WANTALLKEYS) !is 0) doit = false;
             detail = DWT.TRAVERSE_RETURN;
             break;
@@ -3338,7 +3449,7 @@
         case OS.VK_TAB: {
             lastAscii = '\t';
             bool next = OS.GetKeyState (OS.VK_SHIFT) >= 0;
-            int code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0);
+            int /*long*/ code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0);
             if ((code & (OS.DLGC_WANTTAB | OS.DLGC_WANTALLKEYS)) !is 0) {
                 /*
                 * Use DLGC_HASSETSEL to determine that the control is a
@@ -3356,9 +3467,6 @@
                     doit = false;
                 }
             }
-            if (parent !is null && (parent.style & DWT.MIRRORED) !is 0) {
-                if (key is OS.VK_LEFT || key is OS.VK_RIGHT) next = !next;
-            }
             detail = next ? DWT.TRAVERSE_TAB_NEXT : DWT.TRAVERSE_TAB_PREVIOUS;
             break;
         }
@@ -3375,9 +3483,12 @@
                 if (key is OS.VK_LEFT || key is OS.VK_RIGHT) return false;
             }
             lastVirtual = true;
-            int code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0);
+            int /*long*/ code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0);
             if ((code & (OS.DLGC_WANTARROWS /*| OS.DLGC_WANTALLKEYS*/)) !is 0) doit = false;
             bool next = key is OS.VK_DOWN || key is OS.VK_RIGHT;
+            if (parent !is null && (parent.style & DWT.MIRRORED) !is 0) {
+                if (key is OS.VK_LEFT || key is OS.VK_RIGHT) next = !next;
+            }
             detail = next ? DWT.TRAVERSE_ARROW_NEXT : DWT.TRAVERSE_ARROW_PREVIOUS;
             break;
         }
@@ -3386,7 +3497,7 @@
             all = true;
             lastVirtual = true;
             if (OS.GetKeyState (OS.VK_CONTROL) >= 0) return false;
-            int code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0);
+            int /*long*/ code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0);
             if ((code & OS.DLGC_WANTALLKEYS) !is 0) {
                 /*
                 * Use DLGC_HASSETSEL to determine that the control is a
@@ -3546,10 +3657,10 @@
 }
 
 void unsubclass () {
-    int newProc = windowProc ();
-    int oldProc = display.windowProc;
+    int /*long*/ newProc = windowProc ();
+    int /*long*/ oldProc = display.windowProc;
     if (oldProc is newProc) return;
-    OS.SetWindowLong (handle, OS.GWL_WNDPROC, newProc);
+    OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, newProc);
 }
 
 /**
@@ -3711,13 +3822,14 @@
 
 abstract String windowClass ();
 
-abstract int windowProc ();
+abstract int /*long*/ windowProc ();
 
 int windowProc (HWND hwnd, int msg, int wParam, int lParam) {
     LRESULT result = null;
     switch (msg) {
         case OS.WM_ACTIVATE:            result = WM_ACTIVATE (wParam, lParam); break;
         case OS.WM_CAPTURECHANGED:      result = WM_CAPTURECHANGED (wParam, lParam); break;
+        case OS.WM_CHANGEUISTATE:       result = WM_CHANGEUISTATE (wParam, lParam); break;
         case OS.WM_CHAR:                result = WM_CHAR (wParam, lParam); break;
         case OS.WM_CLEAR:               result = WM_CLEAR (wParam, lParam); break;
         case OS.WM_CLOSE:               result = WM_CLOSE (wParam, lParam); break;
@@ -3744,6 +3856,8 @@
         case OS.WM_HSCROLL:             result = WM_HSCROLL (wParam, lParam); break;
         case OS.WM_IME_CHAR:            result = WM_IME_CHAR (wParam, lParam); break;
         case OS.WM_IME_COMPOSITION:     result = WM_IME_COMPOSITION (wParam, lParam); break;
+        case OS.WM_IME_COMPOSITION_START:   result = WM_IME_COMPOSITION_START (wParam, lParam); break;
+        case OS.WM_IME_ENDCOMPOSITION:  result = WM_IME_ENDCOMPOSITION (wParam, lParam); break;
         case OS.WM_INITMENUPOPUP:       result = WM_INITMENUPOPUP (wParam, lParam); break;
         case OS.WM_INPUTLANGCHANGE:     result = WM_INPUTLANGCHANGE (wParam, lParam); break;
         case OS.WM_HOTKEY:              result = WM_HOTKEY (wParam, lParam); break;
@@ -3810,27 +3924,32 @@
     return callWindowProc (hwnd, msg, wParam, lParam);
 }
 
-LRESULT WM_ACTIVATE (int wParam, int lParam) {
+LRESULT WM_ACTIVATE (int /*long*/ wParam, int /*long*/ lParam) {
     return null;
 }
 
-LRESULT WM_CAPTURECHANGED (int wParam, int lParam) {
+LRESULT WM_CAPTURECHANGED (int /*long*/ wParam, int /*long*/ lParam) {
     return wmCaptureChanged (handle, wParam, lParam);
 }
 
-LRESULT WM_CHAR (int wParam, int lParam) {
+LRESULT WM_CHANGEUISTATE (int /*long*/ wParam, int /*long*/ lParam) {
+    if ((state & IGNORE_WM_CHANGEUISTATE) !is 0) return LRESULT.ZERO;
+    return null;
+}
+
+LRESULT WM_CHAR (int /*long*/ wParam, int /*long*/ lParam) {
     return wmChar (handle, wParam, lParam);
 }
 
-LRESULT WM_CLEAR (int wParam, int lParam) {
+LRESULT WM_CLEAR (int /*long*/ wParam, int /*long*/ lParam) {
     return null;
 }
 
-LRESULT WM_CLOSE (int wParam, int lParam) {
+LRESULT WM_CLOSE (int /*long*/ wParam, int /*long*/ lParam) {
     return null;
 }
 
-LRESULT WM_COMMAND (int wParam, int lParam) {
+LRESULT WM_COMMAND (int /*long*/ wParam, int /*long*/ lParam) {
     /*
     * When the WM_COMMAND message is sent from a
     * menu, the HWND parameter in LPARAM is zero.
@@ -3838,7 +3957,7 @@
     if (lParam is 0) {
         Decorations shell = menuShell ();
         if (shell.isEnabled ()) {
-            int id = wParam & 0xFFFF;
+            int id = OS.LOWORD (wParam);
             MenuItem item = display.getMenuItem (id);
             if (item !is null && item.isEnabled ()) {
                 return item.wmCommandChild (wParam, lParam);
@@ -3851,11 +3970,11 @@
     return control.wmCommandChild (wParam, lParam);
 }
 
-LRESULT WM_CONTEXTMENU (int wParam, int lParam) {
+LRESULT WM_CONTEXTMENU (int /*long*/ wParam, int /*long*/ lParam) {
     return wmContextMenu (handle, wParam, lParam);
 }
 
-LRESULT WM_CTLCOLOR (int wParam, int lParam) {
+LRESULT WM_CTLCOLOR (int /*long*/ wParam, int /*long*/ lParam) {
     auto hPalette = display.hPalette;
     if (hPalette !is null) {
         OS.SelectPalette ( cast(HPALETTE)wParam, hPalette, false);
@@ -3866,15 +3985,15 @@
     return control.wmColorChild (wParam, lParam);
 }
 
-LRESULT WM_CUT (int wParam, int lParam) {
+LRESULT WM_CUT (int /*long*/ wParam, int /*long*/ lParam) {
     return null;
 }
 
-LRESULT WM_DESTROY (int wParam, int lParam) {
+LRESULT WM_DESTROY (int /*long*/ wParam, int /*long*/ lParam) {
     return null;
 }
 
-LRESULT WM_DRAWITEM (int wParam, int lParam) {
+LRESULT WM_DRAWITEM (int /*long*/ wParam, int /*long*/ lParam) {
     DRAWITEMSTRUCT* struct_ = cast(DRAWITEMSTRUCT*)lParam;
     if (struct_.CtlType is OS.ODT_MENU) {
         MenuItem item = display.getMenuItem (struct_.itemID);
@@ -3886,15 +4005,15 @@
     return control.wmDrawChild (wParam, lParam);
 }
 
-LRESULT WM_ENDSESSION (int wParam, int lParam) {
+LRESULT WM_ENDSESSION (int /*long*/ wParam, int /*long*/ lParam) {
     return null;
 }
 
-LRESULT WM_ENTERIDLE (int wParam, int lParam) {
+LRESULT WM_ENTERIDLE (int /*long*/ wParam, int /*long*/ lParam) {
     return null;
 }
 
-LRESULT WM_ERASEBKGND (int wParam, int lParam) {
+LRESULT WM_ERASEBKGND (int /*long*/ wParam, int /*long*/ lParam) {
     if ((state & DRAW_BACKGROUND) !is 0) {
         if (findImageControl () !is null) return LRESULT.ONE;
     }
@@ -3906,31 +4025,31 @@
     return null;
 }
 
-LRESULT WM_GETDLGCODE (int wParam, int lParam) {
+LRESULT WM_GETDLGCODE (int /*long*/ wParam, int /*long*/ lParam) {
     return null;
 }
 
-LRESULT WM_GETFONT (int wParam, int lParam) {
+LRESULT WM_GETFONT (int /*long*/ wParam, int /*long*/ lParam) {
     return null;
 }
 
-LRESULT WM_GETOBJECT (int wParam, int lParam) {
+LRESULT WM_GETOBJECT (int /*long*/ wParam, int /*long*/ lParam) {
     if (accessible !is null) {
-        int result = accessible.internal_WM_GETOBJECT (wParam, lParam);
+        int /*long*/ result = accessible.internal_WM_GETOBJECT (wParam, lParam);
         if (result !is 0) return new LRESULT (result);
     }
     return null;
 }
 
-LRESULT WM_GETMINMAXINFO (int wParam, int lParam) {
+LRESULT WM_GETMINMAXINFO (int /*long*/ wParam, int /*long*/ lParam) {
     return null;
 }
 
-LRESULT WM_HOTKEY (int wParam, int lParam) {
+LRESULT WM_HOTKEY (int /*long*/ wParam, int /*long*/ lParam) {
     return null;
 }
 
-LRESULT WM_HELP (int wParam, int lParam) {
+LRESULT WM_HELP (int /*long*/ wParam, int /*long*/ lParam) {
     static if (OS.IsWinCE) return null;
     HELPINFO* lphi = cast(HELPINFO*)lParam;
     Decorations shell = menuShell ();
@@ -3961,21 +4080,29 @@
     return null;
 }
 
-LRESULT WM_HSCROLL (int wParam, int lParam) {
+LRESULT WM_HSCROLL (int /*long*/ wParam, int /*long*/ lParam) {
     Control control = display.getControl (cast(HANDLE)lParam);
     if (control is null) return null;
     return control.wmScrollChild (wParam, lParam);
 }
 
-LRESULT WM_IME_CHAR (int wParam, int lParam) {
+LRESULT WM_IME_CHAR (int /*long*/ wParam, int /*long*/ lParam) {
     return wmIMEChar (handle, wParam, lParam);
 }
 
-LRESULT WM_IME_COMPOSITION (int wParam, int lParam) {
+LRESULT WM_IME_COMPOSITION (int /*long*/ wParam, int /*long*/ lParam) {
+    return null;
+}
+
+LRESULT WM_IME_COMPOSITION_START (int /*long*/ wParam, int /*long*/ lParam) {
     return null;
 }
 
-LRESULT WM_INITMENUPOPUP (int wParam, int lParam) {
+LRESULT WM_IME_ENDCOMPOSITION (int /*long*/ wParam, int /*long*/ lParam) {
+    return null;
+}
+
+LRESULT WM_INITMENUPOPUP (int /*long*/ wParam, int /*long*/ lParam) {
 
     /* Ignore WM_INITMENUPOPUP for an accelerator */
     if (display.accelKeyHit) return null;
@@ -3987,7 +4114,7 @@
     */
     Shell shell = getShell ();
     Menu oldMenu = shell.activeMenu, newMenu = null;
-    if ((lParam >> 16) is 0) {
+    if (OS.HIWORD (lParam) is 0) {
         newMenu = menuShell ().findMenu (cast(HANDLE)wParam);
         if (newMenu !is null) newMenu.update ();
     }
@@ -4032,47 +4159,47 @@
     return null;
 }
 
-LRESULT WM_INPUTLANGCHANGE (int wParam, int lParam) {
+LRESULT WM_INPUTLANGCHANGE (int /*long*/ wParam, int /*long*/ lParam) {
     return null;
 }
 
-LRESULT WM_KEYDOWN (int wParam, int lParam) {
+LRESULT WM_KEYDOWN (int /*long*/ wParam, int /*long*/ lParam) {
     return wmKeyDown (handle, wParam, lParam);
 }
 
-LRESULT WM_KEYUP (int wParam, int lParam) {
+LRESULT WM_KEYUP (int /*long*/ wParam, int /*long*/ lParam) {
     return wmKeyUp (handle, wParam, lParam);
 }
 
-LRESULT WM_KILLFOCUS (int wParam, int lParam) {
+LRESULT WM_KILLFOCUS (int /*long*/ wParam, int /*long*/ lParam) {
     return wmKillFocus (handle, wParam, lParam);
 }
 
-LRESULT WM_LBUTTONDBLCLK (int wParam, int lParam) {
+LRESULT WM_LBUTTONDBLCLK (int /*long*/ wParam, int /*long*/ lParam) {
     return wmLButtonDblClk (handle, wParam, lParam);
 }
 
-LRESULT WM_LBUTTONDOWN (int wParam, int lParam) {
+LRESULT WM_LBUTTONDOWN (int /*long*/ wParam, int /*long*/ lParam) {
     return wmLButtonDown (handle, wParam, lParam);
 }
 
-LRESULT WM_LBUTTONUP (int wParam, int lParam) {
+LRESULT WM_LBUTTONUP (int /*long*/ wParam, int /*long*/ lParam) {
     return wmLButtonUp (handle, wParam, lParam);
 }
 
-LRESULT WM_MBUTTONDBLCLK (int wParam, int lParam) {
+LRESULT WM_MBUTTONDBLCLK (int /*long*/ wParam, int /*long*/ lParam) {
     return wmMButtonDblClk (handle, wParam, lParam);
 }
 
-LRESULT WM_MBUTTONDOWN (int wParam, int lParam) {
+LRESULT WM_MBUTTONDOWN (int /*long*/ wParam, int /*long*/ lParam) {
     return wmMButtonDown (handle, wParam, lParam);
 }
 
-LRESULT WM_MBUTTONUP (int wParam, int lParam) {
+LRESULT WM_MBUTTONUP (int /*long*/ wParam, int /*long*/ lParam) {
     return wmMButtonUp (handle, wParam, lParam);
 }
 
-LRESULT WM_MEASUREITEM (int wParam, int lParam) {
+LRESULT WM_MEASUREITEM (int /*long*/ wParam, int /*long*/ lParam) {
     MEASUREITEMSTRUCT* struct_ = cast(MEASUREITEMSTRUCT*)lParam;;
     if (struct_.CtlType is OS.ODT_MENU) {
         MenuItem item = display.getMenuItem (struct_.itemID);
@@ -4085,7 +4212,7 @@
     return control.wmMeasureChild (wParam, lParam);
 }
 
-LRESULT WM_MENUCHAR (int wParam, int lParam) {
+LRESULT WM_MENUCHAR (int /*long*/ wParam, int /*long*/ lParam) {
     /*
     * Feature in Windows.  When the user types Alt+<key>
     * and <key> does not match a mnemonic in the System
@@ -4094,18 +4221,18 @@
     * for Alt+<key>.  The fix is to detect the case and
     * stop Windows from beeping by closing the menu.
     */
-    int type = wParam >> 16;
+    int type = OS.HIWORD (wParam);
     if (type is 0 || type is OS.MF_SYSMENU) {
         display.mnemonicKeyHit = false;
-        return new LRESULT (OS.MNC_CLOSE << 16);
+        return new LRESULT (OS.MAKELRESULT (0, OS.MNC_CLOSE));
     }
     return null;
 }
 
-LRESULT WM_MENUSELECT (int wParam, int lParam) {
-    int code = wParam >> 16;
+LRESULT WM_MENUSELECT (int /*long*/ wParam, int /*long*/ lParam) {
+    int code = OS.HIWORD (wParam);
     Shell shell = getShell ();
-    if (code is -1 && lParam is 0) {
+    if (code is 0xFFFF && lParam is 0) {
         Menu menu = shell.activeMenu;
         while (menu !is null) {
             /*
@@ -4142,7 +4269,7 @@
         MenuItem item = null;
         Decorations menuShell = menuShell ();
         if ((code & OS.MF_POPUP) !is 0) {
-            int index = wParam & 0xFFFF;
+            int index = OS.LOWORD (wParam);
             MENUITEMINFO info;
             info.cbSize = MENUITEMINFO.sizeof;
             info.fMask = OS.MIIM_SUBMENU;
@@ -4153,7 +4280,7 @@
         } else {
             Menu newMenu = menuShell.findMenu (cast(HANDLE)lParam);
             if (newMenu !is null) {
-                int id = wParam & 0xFFFF;
+                int id = OS.LOWORD (wParam);
                 item = display.getMenuItem (id);
             }
             Menu oldMenu = shell.activeMenu;
@@ -4175,6 +4302,7 @@
                         ancestor.sendEvent (DWT.Hide);
                         if (ancestor.isDisposed ()) break;
                         ancestor = ancestor.getParentMenu ();
+                        if (ancestor is null) break;
                     }
                     /*
                     * The shell and/or the item could be disposed when
@@ -4197,28 +4325,29 @@
     return null;
 }
 
-LRESULT WM_MOUSEACTIVATE (int wParam, int lParam) {
+LRESULT WM_MOUSEACTIVATE (int /*long*/ wParam, int /*long*/ lParam) {
     return null;
 }
 
-LRESULT WM_MOUSEHOVER (int wParam, int lParam) {
+LRESULT WM_MOUSEHOVER (int /*long*/ wParam, int /*long*/ lParam) {
     return wmMouseHover (handle, wParam, lParam);
 }
 
-LRESULT WM_MOUSELEAVE (int wParam, int lParam) {
+LRESULT WM_MOUSELEAVE (int /*long*/ wParam, int /*long*/ lParam) {
     if (OS.COMCTL32_MAJOR >= 6) getShell ().fixToolTip ();
     return wmMouseLeave (handle, wParam, lParam);
 }
 
-LRESULT WM_MOUSEMOVE (int wParam, int lParam) {
+LRESULT WM_MOUSEMOVE (int /*long*/ wParam, int /*long*/ lParam) {
     return wmMouseMove (handle, wParam, lParam);
 }
 
-LRESULT WM_MOUSEWHEEL (int wParam, int lParam) {
+LRESULT WM_MOUSEWHEEL (int /*long*/ wParam, int /*long*/ lParam) {
     return wmMouseWheel (handle, wParam, lParam);
 }
 
-LRESULT WM_MOVE (int wParam, int lParam) {
+LRESULT WM_MOVE (int /*long*/ wParam, int /*long*/ lParam) {
+    state |= MOVE_OCCURRED;
     if (findImageControl () !is null) {
         if (this !is getShell ()) redrawChildren ();
     } else {
@@ -4230,88 +4359,88 @@
             }
         }
     }
-    sendEvent (DWT.Move);
+    if ((state & MOVE_DEFERRED) is 0) sendEvent (DWT.Move);
     // widget could be disposed at this point
     return null;
 }
 
-LRESULT WM_NCACTIVATE (int wParam, int lParam) {
+LRESULT WM_NCACTIVATE (int /*long*/ wParam, int /*long*/ lParam) {
     return null;
 }
 
-LRESULT WM_NCCALCSIZE (int wParam, int lParam) {
+LRESULT WM_NCCALCSIZE (int /*long*/ wParam, int /*long*/ lParam) {
     return null;
 }
 
-LRESULT WM_NCHITTEST (int wParam, int lParam) {
+LRESULT WM_NCHITTEST (int /*long*/ wParam, int /*long*/ lParam) {
     if (!OS.IsWindowEnabled (handle)) return null;
     if (!isActive ()) return new LRESULT (OS.HTTRANSPARENT);
     return null;
 }
 
-LRESULT WM_NCLBUTTONDOWN (int wParam, int lParam) {
+LRESULT WM_NCLBUTTONDOWN (int /*long*/ wParam, int /*long*/ lParam) {
     return null;
 }
 
-LRESULT WM_NCPAINT (int wParam, int lParam) {
-    return null;
-}
-
-LRESULT WM_NOTIFY (int wParam, int lParam) {
+LRESULT WM_NCPAINT (int /*long*/ wParam, int /*long*/ lParam) {
+    return wmNCPaint (handle, wParam, lParam);
+}
+
+LRESULT WM_NOTIFY (int /*long*/ wParam, int /*long*/ lParam) {
     NMHDR* hdr = cast(NMHDR*)lParam;
     return wmNotify (hdr, wParam, lParam);
 }
 
-LRESULT WM_PAINT (int wParam, int lParam) {
-    return super.wmPaint (handle, wParam, lParam);
-}
-
-LRESULT WM_PALETTECHANGED (int wParam, int lParam) {
+LRESULT WM_PAINT (int /*long*/ wParam, int /*long*/ lParam) {
+    return wmPaint (handle, wParam, lParam);
+}
+
+LRESULT WM_PALETTECHANGED (int /*long*/ wParam, int /*long*/ lParam) {
     return null;
 }
 
-LRESULT WM_PARENTNOTIFY (int wParam, int lParam) {
+LRESULT WM_PARENTNOTIFY (int /*long*/ wParam, int /*long*/ lParam) {
     return null;
 }
 
-LRESULT WM_PASTE (int wParam, int lParam) {
+LRESULT WM_PASTE (int /*long*/ wParam, int /*long*/ lParam) {
     return null;
 }
 
-LRESULT WM_PRINT (int wParam, int lParam) {
+LRESULT WM_PRINT (int /*long*/ wParam, int /*long*/ lParam) {
     return wmPrint (handle, wParam, lParam);
 }
 
-LRESULT WM_PRINTCLIENT (int wParam, int lParam) {
+LRESULT WM_PRINTCLIENT (int /*long*/ wParam, int /*long*/ lParam) {
     return null;
 }
 
-LRESULT WM_QUERYENDSESSION (int wParam, int lParam) {
+LRESULT WM_QUERYENDSESSION (int /*long*/ wParam, int /*long*/ lParam) {
     return null;
 }
 
-LRESULT WM_QUERYNEWPALETTE (int wParam, int lParam) {
+LRESULT WM_QUERYNEWPALETTE (int /*long*/ wParam, int /*long*/ lParam) {
     return null;
 }
 
-LRESULT WM_QUERYOPEN (int wParam, int lParam) {
+LRESULT WM_QUERYOPEN (int /*long*/ wParam, int /*long*/ lParam) {
     return null;
 }
 
-LRESULT WM_RBUTTONDBLCLK (int wParam, int lParam) {
+LRESULT WM_RBUTTONDBLCLK (int /*long*/ wParam, int /*long*/ lParam) {
     return wmRButtonDblClk (handle, wParam, lParam);
 }
 
-LRESULT WM_RBUTTONDOWN (int wParam, int lParam) {
+LRESULT WM_RBUTTONDOWN (int /*long*/ wParam, int /*long*/ lParam) {
     return wmRButtonDown (handle, wParam, lParam);
 }
 
-LRESULT WM_RBUTTONUP (int wParam, int lParam) {
+LRESULT WM_RBUTTONUP (int /*long*/ wParam, int /*long*/ lParam) {
     return wmRButtonUp (handle, wParam, lParam);
 }
 
-LRESULT WM_SETCURSOR (int wParam, int lParam) {
-    int hitTest = cast(short) (lParam & 0xFFFF);
+LRESULT WM_SETCURSOR (int /*long*/ wParam, int /*long*/ lParam) {
+    int hitTest = cast(short) OS.LOWORD (lParam);
     if (hitTest is OS.HTCLIENT) {
         Control control = display.getControl (cast(HANDLE)wParam);
         if (control is null) return null;
@@ -4324,51 +4453,54 @@
     return null;
 }
 
-LRESULT WM_SETFOCUS (int wParam, int lParam) {
+LRESULT WM_SETFOCUS (int /*long*/ wParam, int /*long*/ lParam) {
     return wmSetFocus (handle, wParam, lParam);
 }
 
-LRESULT WM_SETTINGCHANGE (int wParam, int lParam) {
+LRESULT WM_SETTINGCHANGE (int /*long*/ wParam, int /*long*/ lParam) {
     return null;
 }
 
-LRESULT WM_SETFONT (int wParam, int lParam) {
+LRESULT WM_SETFONT (int /*long*/ wParam, int /*long*/ lParam) {
     return null;
 }
 
-LRESULT WM_SETREDRAW (int wParam, int lParam) {
+LRESULT WM_SETREDRAW (int /*long*/ wParam, int /*long*/ lParam) {
+    return null;
+}
+
+LRESULT WM_SHOWWINDOW (int /*long*/ wParam, int /*long*/ lParam) {
     return null;
 }
 
-LRESULT WM_SHOWWINDOW (int wParam, int lParam) {
-    return null;
-}
-
-LRESULT WM_SIZE (int wParam, int lParam) {
-    sendEvent (DWT.Resize);
+LRESULT WM_SIZE (int /*long*/ wParam, int /*long*/ lParam) {
+    state |= RESIZE_OCCURRED;
+    if ((state & RESIZE_DEFERRED) is 0) sendEvent (DWT.Resize);
     // widget could be disposed at this point
     return null;
 }
 
-LRESULT WM_SYSCHAR (int wParam, int lParam) {
+LRESULT WM_SYSCHAR (int /*long*/ wParam, int /*long*/ lParam) {
     return wmSysChar (handle, wParam, lParam);
 }
 
-LRESULT WM_SYSCOLORCHANGE (int wParam, int lParam) {
+LRESULT WM_SYSCOLORCHANGE (int /*long*/ wParam, int /*long*/ lParam) {
     return null;
 }
 
-LRESULT WM_SYSCOMMAND (int wParam, int lParam) {
+LRESULT WM_SYSCOMMAND (int /*long*/ wParam, int /*long*/ lParam) {
     /*
     * Check to see if the command is a system command or
     * a user menu item that was added to the System menu.
     * When a user item is added to the System menu,
     * WM_SYSCOMMAND must always return zero.
+    *
+    * NOTE: This is undocumented.
     */
     if ((wParam & 0xF000) is 0) {
         Decorations shell = menuShell ();
         if (shell.isEnabled ()) {
-            MenuItem item = display.getMenuItem (wParam & 0xFFFF);
+            MenuItem item = display.getMenuItem (OS.LOWORD (wParam));
             if (item !is null) item.wmCommandChild (wParam, lParam);
         }
         return LRESULT.ZERO;
@@ -4472,37 +4604,43 @@
     return null;
 }
 
-LRESULT WM_SYSKEYDOWN (int wParam, int lParam) {
+LRESULT WM_SYSKEYDOWN (int /*long*/ wParam, int /*long*/ lParam) {
     return wmSysKeyDown (handle, wParam, lParam);
 }
 
-LRESULT WM_SYSKEYUP (int wParam, int lParam) {
+LRESULT WM_SYSKEYUP (int /*long*/ wParam, int /*long*/ lParam) {
     return wmSysKeyUp (handle, wParam, lParam);
 }
 
-LRESULT WM_TIMER (int wParam, int lParam) {
+LRESULT WM_TIMER (int /*long*/ wParam, int /*long*/ lParam) {
     return null;
 }
 
-LRESULT WM_UNDO (int wParam, int lParam) {
+LRESULT WM_UNDO (int /*long*/ wParam, int /*long*/ lParam) {
     return null;
 }
 
-LRESULT WM_UPDATEUISTATE (int wParam, int lParam) {
+LRESULT WM_UPDATEUISTATE (int /*long*/ wParam, int /*long*/ lParam) {
     return null;
 }
 
-LRESULT WM_VSCROLL (int wParam, int lParam) {
+LRESULT WM_VSCROLL (int /*long*/ wParam, int /*long*/ lParam) {
     Control control = display.getControl (cast(HANDLE)lParam);
     if (control is null) return null;
     return control.wmScrollChild (wParam, lParam);
 }
 
-LRESULT WM_WINDOWPOSCHANGED (int wParam, int lParam) {
-    return null;
-}
-
-LRESULT WM_WINDOWPOSCHANGING (int wParam, int lParam) {
+LRESULT WM_WINDOWPOSCHANGED (int /*long*/ wParam, int /*long*/ lParam) {
+    try {
+        display.resizeCount++;
+        int /*long*/ code = callWindowProc (handle, OS.WM_WINDOWPOSCHANGED, wParam, lParam);
+        return code is 0 ? LRESULT.ZERO : new LRESULT (code);
+    } finally {
+        --display.resizeCount;
+    }
+}
+
+LRESULT WM_WINDOWPOSCHANGING (int /*long*/ wParam, int /*long*/ lParam) {
     /*
     * Bug in Windows.  When WM_SETREDRAW is used to turn off drawing
     * for a control and the control is moved or resized, Windows does
@@ -4516,28 +4654,42 @@
             if ((lpwp.flags & OS.SWP_NOMOVE) is 0 || (lpwp.flags & OS.SWP_NOSIZE) is 0) {
                 RECT rect;
                 OS.GetWindowRect (topHandle (), &rect);
-                auto hwndParent = parent is null ? null : parent.handle;
-                OS.MapWindowPoints (null, hwndParent, cast(POINT*)&rect, 2);
-                OS.InvalidateRect (hwndParent, &rect, true);
+                int width = rect.right - rect.left;
+                int height = rect.bottom - rect.top;
+                if (width !is 0 && height !is 0) {
+                    auto hwndParent = parent is null ? null : parent.handle;
+                    OS.MapWindowPoints (null, hwndParent, cast(POINT*)&rect, 2);
+                    static if (OS.IsWinCE) {
+                        OS.InvalidateRect (hwndParent, &rect, true);
+                    } else {
+                        auto rgn1 = OS.CreateRectRgn (rect.left, rect.top, rect.right, rect.bottom);
+                        auto rgn2 = OS.CreateRectRgn (lpwp.x, lpwp.y, lpwp.x + lpwp.cx, lpwp.y + lpwp.cy);
+                        OS.CombineRgn (rgn1, rgn1, rgn2, OS.RGN_DIFF);
+                        int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_ALLCHILDREN;
+                        OS.RedrawWindow (hwndParent, null, rgn1, flags);
+                        OS.DeleteObject (rgn1);
+                        OS.DeleteObject (rgn2);
+                    }
+                }
             }
         }
     }
     return null;
 }
 
-LRESULT WM_XBUTTONDBLCLK (int wParam, int lParam) {
+LRESULT WM_XBUTTONDBLCLK (int /*long*/ wParam, int /*long*/ lParam) {
     return wmXButtonDblClk (handle, wParam, lParam);
 }
 
-LRESULT WM_XBUTTONDOWN (int wParam, int lParam) {
+LRESULT WM_XBUTTONDOWN (int /*long*/ wParam, int /*long*/ lParam) {
     return wmXButtonDown (handle, wParam, lParam);
 }
 
-LRESULT WM_XBUTTONUP (int wParam, int lParam) {
+LRESULT WM_XBUTTONUP (int /*long*/ wParam, int /*long*/ lParam) {
     return wmXButtonUp (handle, wParam, lParam);
 }
 
-LRESULT wmColorChild (int wParam, int lParam) {
+LRESULT wmColorChild (int /*long*/ wParam, int /*long*/ lParam) {
     Control control = findBackgroundControl ();
     if (control is null) {
         if ((state & THEME_BACKGROUND) !is 0) {
@@ -4591,15 +4743,15 @@
     return new LRESULT ( cast(int) hBrush);
 }
 
-LRESULT wmCommandChild (int wParam, int lParam) {
+LRESULT wmCommandChild (int /*long*/ wParam, int /*long*/ lParam) {
     return null;
 }
 
-LRESULT wmDrawChild (int wParam, int lParam) {
+LRESULT wmDrawChild (int /*long*/ wParam, int /*long*/ lParam) {
     return null;
 }
 
-LRESULT wmMeasureChild (int wParam, int lParam) {
+LRESULT wmMeasureChild (int /*long*/ wParam, int /*long*/ lParam) {
     return null;
 }
 
@@ -4613,7 +4765,7 @@
     return null;
 }
 
-LRESULT wmScrollChild (int wParam, int lParam) {
+LRESULT wmScrollChild (int /*long*/ wParam, int /*long*/ lParam) {
     return null;
 }
 
--- a/dwt/widgets/CoolBar.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/CoolBar.d	Sat May 17 17:34:28 2008 +0200
@@ -1102,7 +1102,7 @@
     */
     if (OS.COMCTL32_MAJOR >= 6) return LRESULT.ZERO;
     Rectangle rect = getBounds ();
-    int code = callWindowProc (handle, OS.WM_SETREDRAW, wParam, lParam);
+    int /*long*/ code = callWindowProc (handle, OS.WM_SETREDRAW, wParam, lParam);
     OS.DefWindowProc (handle, OS.WM_SETREDRAW, wParam, lParam);
     if ( rect != getBounds ()) {
         parent.redraw (rect.x, rect.y, rect.width, rect.height, true);
@@ -1112,7 +1112,7 @@
 
 override LRESULT WM_SIZE (int wParam, int lParam) {
     if (ignoreResize) {
-        int code = callWindowProc (handle, OS.WM_SIZE, wParam, lParam);
+        int /*long*/ code = callWindowProc (handle, OS.WM_SIZE, wParam, lParam);
         if (code is 0) return LRESULT.ZERO;
         return new LRESULT (code);
     }
@@ -1130,8 +1130,7 @@
         case OS.RBN_BEGINDRAG: {
             int pos = OS.GetMessagePos ();
             POINT pt;
-            pt.x = cast(short) (pos & 0xFFFF);
-            pt.y = cast(short) (pos >> 16);
+            OS.POINTSTOPOINT (pt, pos);
             OS.ScreenToClient (handle, &pt);
             int button = display.lastButton !is 0 ? display.lastButton : 1;
             if (!sendDragEvent (button, pt.x, pt.y)) return LRESULT.ONE;
--- a/dwt/widgets/DateTime.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/DateTime.d	Sat May 17 17:34:28 2008 +0200
@@ -13,7 +13,6 @@
 module dwt.widgets.DateTime;
 
 import dwt.widgets.Composite;
-
 import dwt.DWT;
 import dwt.DWTException;
 import dwt.events.SelectionEvent;
@@ -26,6 +25,7 @@
 import dwt.dwthelper.utils;
 
 import Integer = tango.text.convert.Integer;
+import tango.text.convert.Format;
 
 //TODO - features not yet implemented: read-only, drop-down calendar for date
 //TODO - font, colors, background image not yet implemented (works on some platforms)
@@ -59,6 +59,9 @@
     alias Composite.computeSize computeSize;
     alias Composite.windowProc windowProc;
 
+    bool ignoreSelection;
+    SYSTEMTIME* lastSystemTime;
+    SYSTEMTIME time; // only used in calendar mode
     static /+const+/ WNDPROC DateTimeProc;
     static const TCHAR* DateTimeClass = OS.DATETIMEPICK_CLASS.ptr;
     static /+const+/ WNDPROC CalendarProc;
@@ -356,6 +359,12 @@
 override void createHandle () {
     super.createHandle ();
     state &= ~(CANVAS | THEME_BACKGROUND);
+
+    if ((style & DWT.BORDER) is 0) {
+        int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
+        bits &= ~(OS.WS_EX_CLIENTEDGE | OS.WS_EX_STATICEDGE);
+        OS.SetWindowLong (handle, OS.GWL_EXSTYLE, bits);
+    }
 }
 
 override int defaultBackground () {
@@ -518,6 +527,7 @@
  */
 public int getHours () {
     checkWidget ();
+    if ((style & DWT.CALENDAR) !is 0) return time.wHour;
     SYSTEMTIME systime;
     int msg = (style & DWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME;
     OS.SendMessage (handle, msg, 0, &systime);
@@ -539,6 +549,7 @@
  */
 public int getMinutes () {
     checkWidget ();
+    if ((style & DWT.CALENDAR) !is 0) return time.wMinute;
     SYSTEMTIME systime;
     int msg = (style & DWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME;
     OS.SendMessage (handle, msg, 0, &systime);
@@ -567,7 +578,8 @@
 }
 
 override String getNameText () {
-    return "DateTime";
+    return (style & DWT.TIME) !is 0 ? Format( "{}:{}:{}", getHours(), getMinutes(), getSeconds())
+            : Format("{}/{}/{}", (getMonth() + 1), getDay(), getYear());
 }
 
 /**
@@ -585,6 +597,7 @@
  */
 public int getSeconds () {
     checkWidget ();
+    if ((style & DWT.CALENDAR) !is 0) return time.wSecond;
     SYSTEMTIME systime;
     int msg = (style & DWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME;
     OS.SendMessage (handle, msg, 0, &systime);
@@ -612,6 +625,11 @@
     return systime.wYear;
 }
 
+void releaseWidget () {
+    super.releaseWidget ();
+    lastSystemTime = null;
+}
+
 /**
  * Removes the listener from the collection of listeners who will
  * be notified when the control is selected by the user.
@@ -638,6 +656,37 @@
 }
 
 /**
+ * Sets the receiver's year, month, and day in a single operation.
+ * <p>
+ * This is the recommended way to set the date, because setting the year,
+ * month, and day separately may result in invalid intermediate dates.
+ * </p>
+ *
+ * @param year an integer between 1752 and 9999
+ * @param month an integer between 0 and 11
+ * @param day a positive integer beginning with 1
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @since 3.4
+ */
+public void setDate (int year, int month, int day) {
+    checkWidget ();
+    SYSTEMTIME systime;
+    int msg = (style & DWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME;
+    OS.SendMessage (handle, msg, 0, &systime);
+    msg = (style & DWT.CALENDAR) !is 0 ? OS.MCM_SETCURSEL : OS.DTM_SETSYSTEMTIME;
+    systime.wYear = cast(short)year;
+    systime.wMonth = cast(short)(month + 1);
+    systime.wDay = cast(short)day;
+    OS.SendMessage (handle, msg, 0, &systime);
+    lastSystemTime = null;
+}
+
+/**
  * Sets the receiver's date, or day of the month, to the specified day.
  * <p>
  * The first day of the month is 1, and the last day depends on the month and year.
@@ -658,6 +707,7 @@
     msg = (style & DWT.CALENDAR) !is 0 ? OS.MCM_SETCURSEL : OS.DTM_SETSYSTEMTIME;
     systime.wDay = cast(short)day;
     OS.SendMessage (handle, msg, 0, &systime);
+    lastSystemTime = null;
 }
 
 /**
@@ -681,6 +731,7 @@
     msg = (style & DWT.CALENDAR) !is 0 ? OS.MCM_SETCURSEL : OS.DTM_SETSYSTEMTIME;
     systime.wHour = cast(short)hours;
     OS.SendMessage (handle, msg, 0, &systime);
+    if ((style & DWT.CALENDAR) !is 0 && hours >= 0 && hours <= 23) time.wHour = cast(short)hours;
 }
 
 /**
@@ -704,6 +755,7 @@
     msg = (style & DWT.CALENDAR) !is 0 ? OS.MCM_SETCURSEL : OS.DTM_SETSYSTEMTIME;
     systime.wMinute = cast(short)minutes;
     OS.SendMessage (handle, msg, 0, &systime);
+    if ((style & DWT.CALENDAR) !is 0 && minutes >= 0 && minutes <= 59) time.wMinute = cast(short)minutes;
 }
 
 /**
@@ -727,6 +779,7 @@
     msg = (style & DWT.CALENDAR) !is 0 ? OS.MCM_SETCURSEL : OS.DTM_SETSYSTEMTIME;
     systime.wMonth = cast(short)(month + 1);
     OS.SendMessage (handle, msg, 0, &systime);
+    lastSystemTime = null;
 }
 
 /**
@@ -750,6 +803,41 @@
     msg = (style & DWT.CALENDAR) !is 0 ? OS.MCM_SETCURSEL : OS.DTM_SETSYSTEMTIME;
     systime.wSecond = cast(short)seconds;
     OS.SendMessage (handle, msg, 0, &systime);
+    if ((style & DWT.CALENDAR) !is 0 && seconds >= 0 && seconds <= 59) time.wSecond = cast(short)seconds;
+}
+
+/**
+ * Sets the receiver's hours, minutes, and seconds in a single operation.
+ *
+ * @param hours an integer between 0 and 23
+ * @param minutes an integer between 0 and 59
+ * @param seconds an integer between 0 and 59
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @since 3.4
+ */
+public void setTime (int hours, int minutes, int seconds) {
+    checkWidget ();
+    SYSTEMTIME systime;
+    int msg = (style & DWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME;
+    OS.SendMessage (handle, msg, 0, &systime);
+    msg = (style & DWT.CALENDAR) !is 0 ? OS.MCM_SETCURSEL : OS.DTM_SETSYSTEMTIME;
+    systime.wHour = cast(short)hours;
+    systime.wMinute = cast(short)minutes;
+    systime.wSecond = cast(short)seconds;
+    OS.SendMessage (handle, msg, 0, &systime);
+    if ((style & DWT.CALENDAR) !is 0
+            && hours >= 0 && hours <= 23
+            && minutes >= 0 && minutes <= 59
+            && seconds >= 0 && seconds <= 59) {
+        time.wHour = cast(short)hours;
+        time.wMinute = cast(short)minutes;
+        time.wSecond = cast(short)seconds;
+    }
 }
 
 /**
@@ -773,6 +861,7 @@
     msg = (style & DWT.CALENDAR) !is 0 ? OS.MCM_SETCURSEL : OS.DTM_SETSYSTEMTIME;
     systime.wYear = cast(short)year;
     OS.SendMessage (handle, msg, 0, &systime);
+    lastSystemTime = null;
 }
 
 override int widgetStyle () {
@@ -799,13 +888,37 @@
 
 override LRESULT wmNotifyChild (NMHDR* hdr, int wParam, int lParam) {
     switch (hdr.code) {
-        case OS.MCN_SELCHANGE: //SENT WHEN YOU SET IT?
+        case OS.MCN_SELCHANGE:
         case OS.DTN_DATETIMECHANGE:
-            sendEvent (DWT.Selection);
+            if (ignoreSelection) break;
+            SYSTEMTIME systime;
+            int msg = (style & DWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME;
+            OS.SendMessage (handle, msg, 0, &systime);
+            if (lastSystemTime is null || systime.wDay !is lastSystemTime.wDay || systime.wMonth !is lastSystemTime.wMonth || systime.wYear !is lastSystemTime.wYear) {
+                postEvent (DWT.Selection);
+                if ((style & DWT.TIME) is 0) {
+                    lastSystemTime = new SYSTEMTIME();
+                    *lastSystemTime = systime;
+                }
+            }
             break;
         default:
     }
     return super.wmNotifyChild (hdr, wParam, lParam);
 }
+
+LRESULT WM_TIMER (int /*long*/ wParam, int /*long*/ lParam) {
+    LRESULT result = super.WM_TIMER (wParam, lParam);
+    if (result !is null) return result;
+    /*
+    * Feature in Windows. For some reason, Windows sends WM_NOTIFY with
+    * MCN_SELCHANGE at regular intervals. This is unexpected. The fix is
+    * to ignore MCN_SELCHANGE during WM_TIMER.
+    */
+    ignoreSelection = true;
+    int /*long*/ code = callWindowProc(handle, OS.WM_TIMER, wParam, lParam);
+    ignoreSelection = false;
+    return code is 0 ? LRESULT.ZERO : new LRESULT(code);
+}
 }
 
--- a/dwt/widgets/Decorations.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/Decorations.d	Sat May 17 17:34:28 2008 +0200
@@ -310,6 +310,10 @@
     /* Do nothing */
 }
 
+void checkComposited (Composite parent) {
+    /* Do nothing */
+}
+
 override void checkOpened () {
     if (!opened) resized = false;
 }
@@ -412,8 +416,7 @@
                     while (menu !is null && menu !is menuBar) {
                         menu = menu.getParentMenu ();
                     }
-                    if (menu is menuBar) {
-                        item.fillAccel (&accel);
+                    if (menu is menuBar && item.fillAccel (&accel)) {
                         *cast(ACCEL*)buffer1.ptr = accel;
                         //OS.MoveMemory (buffer1, accel, ACCEL.sizeof);
                         System.arraycopy (buffer1, 0, buffer2, nAccel * ACCEL.sizeof, ACCEL.sizeof);
@@ -1218,7 +1221,7 @@
     int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
     bits &= ~OS.WS_CHILD;
     OS.SetWindowLong (handle, OS.GWL_STYLE, bits | OS.WS_POPUP);
-    OS.SetWindowLong (handle, OS.GWL_ID, 0);
+    OS.SetWindowLongPtr (handle, OS.GWLP_ID, 0);
     int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE;
     SetWindowPos (handle, cast(HWND)OS.HWND_BOTTOM, 0, 0, 0, 0, flags);
     display.lockActiveWindow = false;
@@ -1337,7 +1340,18 @@
     checkWidget ();
     if (string is null) error (DWT.ERROR_NULL_ARGUMENT);
     /* Use the character encoding for the default locale */
-    OS.SetWindowText (handle, StrToTCHARz(string));
+    TCHAR[] buffer = StrToTCHARs (string, true);
+    /* Ensure that the title appears in the task bar.*/
+    if ((state & FOREIGN_HANDLE) !is 0) {
+        auto hHeap = OS.GetProcessHeap ();
+        int byteCount = buffer.length * TCHAR.sizeof;
+        auto pszText = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+        OS.MoveMemory (pszText, buffer.ptr, byteCount);
+        OS.DefWindowProc (handle, OS.WM_SETTEXT, 0, cast(int) pszText);
+        if (pszText !is null) OS.HeapFree (hHeap, 0, pszText);
+    } else {
+        OS.SetWindowText (handle, buffer.ptr);
+    }
 }
 
 override public void setVisible (bool visible) {
@@ -1402,11 +1416,7 @@
                 if (OS.IsZoomed (handle)) {
                     swFlags = OS.SW_SHOWMAXIMIZED;
                 } else {
-                    if (handle is OS.GetActiveWindow ()) {
-                        swFlags = OS.SW_RESTORE;
-                    } else {
-                        swFlags = OS.SW_SHOWNOACTIVATE;
-                    }
+                    swFlags = OS.SW_SHOWNOACTIVATE;
                 }
             }
         }
@@ -1462,7 +1472,7 @@
         }
         if (msg.message is OS.WM_KEYDOWN) {
             if (OS.GetKeyState (OS.VK_CONTROL) >= 0) return false;
-            switch (msg.wParam) {
+            switch ((msg.wParam)) {
                 case OS.VK_F4:
                     OS.PostMessage (handle, OS.WM_CLOSE, 0, 0);
                     return true;
@@ -1473,7 +1483,7 @@
             return false;
         }
         if (msg.message is OS.WM_SYSKEYDOWN) {
-            switch (msg.wParam) {
+            switch ((msg.wParam)) {
                 case OS.VK_F4:
                     OS.PostMessage (shell.handle, OS.WM_CLOSE, 0, 0);
                     return true;
@@ -1612,14 +1622,14 @@
             return LRESULT.ZERO;
         }
     }
-    if ((wParam & 0xFFFF) !is 0) {
+    if (OS.LOWORD (wParam) !is 0) {
         /*
         * When the high word of wParam is non-zero, the activation
         * state of the window is being changed while the window is
         * minimized. If this is the case, do not report activation
         * events or restore the focus.
         */
-        if ((wParam >> 16) !is 0) return result;
+        if (OS.HIWORD (wParam) !is 0) return result;
         Control control = display.findControl (cast(HWND)lParam);
         if (control is null || (null !is cast(Shell)control)) {
             if (cast(Shell)this) {
@@ -1672,7 +1682,7 @@
             * If the Shell has the DWT.CLOSE style, close the Shell.
             * Otherwise, send the Back key to the window with focus.
             */
-            if (((lParam >> 16) & 0xFFFF) is OS.VK_ESCAPE) {
+        if (OS.HIWORD (lParam) is OS.VK_ESCAPE) {
                 if ((style & DWT.CLOSE) !is 0) {
                     OS.PostMessage (handle, OS.WM_CLOSE, 0, 0);
                 } else {
@@ -1751,8 +1761,8 @@
         switch (wParam) {
             case OS.SIZE_RESTORED:
             case OS.SIZE_MAXIMIZED:
-                newWidth = lParam & 0xFFFF;
-                newHeight = lParam >> 16;
+                newWidth = OS.LOWORD (lParam);
+                newHeight = OS.HIWORD (lParam);
                 break;
             case OS.SIZE_MINIMIZED:
                 Rectangle rect = getClientArea ();
--- a/dwt/widgets/Dialog.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/Dialog.d	Sat May 17 17:34:28 2008 +0200
@@ -17,6 +17,7 @@
 import dwt.DWTException;
 import dwt.widgets.Shell;
 import dwt.widgets.Display;
+import dwt.widgets.Widget;
 import dwt.dwthelper.utils;
 
 /**
@@ -170,6 +171,20 @@
     parent.checkWidget ();
 }
 
+static int checkStyle (Shell parent, int style) {
+    if ((style & (DWT.PRIMARY_MODAL | DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL)) is 0) {
+        style |= DWT.APPLICATION_MODAL;
+    }
+    style &= ~DWT.MIRRORED;
+    if ((style & (DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT)) is 0) {
+        if (parent !is null) {
+            if ((parent.style & DWT.LEFT_TO_RIGHT) !is 0) style |= DWT.LEFT_TO_RIGHT;
+            if ((parent.style & DWT.RIGHT_TO_LEFT) !is 0) style |= DWT.RIGHT_TO_LEFT;
+        }
+    }
+    return Widget.checkBits (style, DWT.LEFT_TO_RIGHT, DWT.RIGHT_TO_LEFT, 0, 0, 0, 0);
+}
+
 /**
  * Does whatever dialog specific cleanup is required, and then
  * uses the code in <code>DWTError.error</code> to handle the error.
--- a/dwt/widgets/DirectoryDialog.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/DirectoryDialog.d	Sat May 17 17:34:28 2008 +0200
@@ -58,7 +58,7 @@
  * </ul>
  */
 public this (Shell parent) {
-    this (parent, DWT.PRIMARY_MODAL);
+    this (parent, DWT.APPLICATION_MODAL);
 }
 
 /**
@@ -86,7 +86,7 @@
  * </ul>
  */
 public this (Shell parent, int style) {
-    super (parent, style);
+    super (parent, checkStyle (parent, style));
     checkSubclass ();
 }
 
@@ -193,11 +193,11 @@
     if (lpfn is null) DWT.error (DWT.ERROR_NO_MORE_CALLBACKS);
 
     /* Make the parent shell be temporary modal */
-    Shell oldModal = null;
+    Dialog oldModal = null;
     Display display = parent.getDisplay ();
     if ((style & (DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL)) !is 0) {
-        oldModal = display.getModalDialogShell ();
-        display.setModalDialogShell (parent);
+        oldModal = display.getModalDialog ();
+        display.setModalDialog (this);
     }
 
     directoryPath = null;
@@ -245,7 +245,7 @@
 
     /* Clear the temporary dialog modal parent */
     if ((style & (DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL)) !is 0) {
-        display.setModalDialogShell (oldModal);
+        display.setModalDialog (oldModal);
     }
 
     bool success = lpItemIdList !is null;
--- a/dwt/widgets/Display.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/Display.d	Sat May 17 17:34:28 2008 +0200
@@ -30,9 +30,11 @@
 import dwt.graphics.Rectangle;
 import dwt.graphics.Resource;
 import dwt.internal.ImageList;
+import dwt.internal.Library;
 import dwt.internal.win32.OS;
 
 import dwt.widgets.Control;
+import dwt.widgets.Dialog;
 import dwt.widgets.Tray;
 import dwt.widgets.Event;
 import dwt.widgets.EventTable;
@@ -143,7 +145,7 @@
      * platforms and should never be accessed from application code.
      * </p>
      */
-    public MSG msg;
+    public MSG* msg;
 
     /* Windows and Events */
     Event [] eventQueue;
@@ -157,9 +159,9 @@
     EventTable eventTable, filterTable;
 
     /* Widget Table */
+    int freeSlot;
     int [] indexTable;
     Control lastControl, lastGetControl;
-    int freeSlot;
     HANDLE lastHwnd;
     HWND lastGetHwnd;
     Control [] controlTable;
@@ -228,8 +230,8 @@
     //Callback msgFilterCallback;
     //int msgFilterProc_,
     HHOOK filterHook;
-    MSG hookMsg;
-    bool runDragDrop = true;
+    bool runDragDrop = true, dragCancelled = false;
+    MSG* hookMsg;
 
     /* Idle Hook */
     //Callback foregroundIdleCallback;
@@ -248,8 +250,9 @@
 
     /* Sync/Async Widget Communication */
     Synchronizer synchronizer;
-    bool runMessages = true, runMessagesInIdle = false;
+    bool runMessages = true, runMessagesInIdle = false, runMessagesInMessageProc = true;
     static const String RUN_MESSAGES_IN_IDLE_KEY = "org.eclipse.swt.internal.win32.runMessagesInIdle"; //$NON-NLS-1$
+    static final String RUN_MESSAGES_IN_MESSAGE_PROC_KEY = "dwt.internal.win32.runMessagesInMessageProc"; //$NON-NLS-1$
     Thread thread;
 
     /* Display Shutdown */
@@ -260,16 +263,17 @@
     int nextTrayId;
 
     /* Timers */
-    int [] timerIds;
+    int /*long*/ [] timerIds;
     Runnable [] timerList;
-    int nextTimerId = SETTINGS_ID + 1;
+    int /*long*/ nextTimerId = SETTINGS_ID + 1;
     static const int SETTINGS_ID = 100;
     static const int SETTINGS_DELAY = 2000;
 
     /* Keyboard and Mouse */
-    RECT clickRect;
+    RECT* clickRect;
     int clickCount, lastTime, lastButton;
     HWND lastClickHwnd;
+    int scrollRemainder;
     int lastKey, lastAscii, lastMouse;
     bool lastVirtual, lastNull, lastDead;
     ubyte [256] keyboard;
@@ -308,6 +312,15 @@
 
     /* Table */
     char [] tableBuffer;
+    NMHDR* hdr;
+    NMLVDISPINFO* plvfi;
+    HWND hwndParent;
+    int columnCount;
+    bool [] columnVisible;
+
+    /* Resize and move recursion */
+    int resizeCount;
+    static final int RESIZE_LIMIT = 4;
 
     /* Display Data */
     Object data;
@@ -404,7 +417,7 @@
 
     /* Modality */
     Shell [] modalShells;
-    Shell modalDialogShell;
+    Dialog modalDialog;
     static bool TrimEnabled = false;
 
     /* Private DWT Window Messages */
@@ -417,6 +430,7 @@
     static const int SWT_RUNASYNC       = OS.WM_APP + 6;
     static int SWT_TASKBARCREATED;
     static int SWT_RESTORECARET;
+    static int DI_GETDRAGIMAGE;
 
     /* Workaround for Adobe Reader 7.0 */
     int hitCount;
@@ -490,6 +504,8 @@
  */
 public this (DeviceData data) {
     static_this();
+    msg = new MSG();
+    hookMsg = new MSG();
     super (data);
     synchronizer = new Synchronizer (this);
     cursors = new Cursor [DWT.CURSOR_HAND + 1];
@@ -534,7 +550,7 @@
     static if (USE_PROPERTY) {
         OS.SetProp (handle, cast(wchar*)SWT_OBJECT_INDEX, cast(void*) freeSlot + 1);
     } else {
-        OS.SetWindowLong (handle, OS.GWL_USERDATA, freeSlot + 1);
+        OS.SetWindowLongPtr (handle, OS.GWLP_USERDATA, freeSlot + 1);
     }
     int oldSlot = freeSlot;
     freeSlot = indexTable [oldSlot];
@@ -692,8 +708,10 @@
  * @see #syncExec
  */
 public void asyncExec (Runnable runnable) {
-    if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED);
-    synchronizer.asyncExec (runnable);
+    synchronized (Device.classinfo) {
+        if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED);
+        synchronizer.asyncExec (runnable);
+    }
 }
 
 /**
@@ -732,11 +750,13 @@
     if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED);
 }
 
-static synchronized void checkDisplay (Thread thread, bool multiple) {
-    for (int i=0; i<Displays.length; i++) {
-        if (Displays [i] !is null) {
-            if (!multiple) DWT.error (DWT.ERROR_NOT_IMPLEMENTED, null, " [multiple displays]");
-            if (Displays [i].thread is thread) DWT.error (DWT.ERROR_THREAD_INVALID_ACCESS);
+static void checkDisplay (Thread thread, bool multiple) {
+    synchronized (Device.classinfo) {
+        for (int i=0; i<Displays.length; i++) {
+            if (Displays [i] !is null) {
+                if (!multiple) DWT.error (DWT.ERROR_NOT_IMPLEMENTED, null, " [multiple displays]"); //$NON-NLS-1$
+                if (Displays [i].thread is thread) DWT.error (DWT.ERROR_THREAD_INVALID_ACCESS);
+            }
         }
     }
 }
@@ -845,8 +865,8 @@
     bmiHeader.biCompression = OS.BI_RGB;
     byte [] bmi = new byte [BITMAPINFOHEADER.sizeof];
     bmi[ 0 .. BITMAPINFOHEADER.sizeof ] = (cast(byte*)&bmiHeader)[ 0 .. BITMAPINFOHEADER.sizeof ];
-    int[1] pBits;
-    auto memDib = OS.CreateDIBSection (null, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS, pBits.ptr, null, 0);
+    void* pBits;
+    auto memDib = OS.CreateDIBSection (null, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS, &pBits, null, 0);
     if (memDib is null) DWT.error (DWT.ERROR_NO_HANDLES);
     auto oldMemBitmap = OS.SelectObject (memHdc, memDib);
     BITMAP dibBM;
@@ -882,7 +902,7 @@
             }
         }
     }
-    byte [] srcData = (cast(byte*)pBits [0])[ 0 .. sizeInBytes].dup;
+    byte [] srcData = (cast(byte*)pBits)[ 0 .. sizeInBytes].dup;
     if (hMask !is null) {
         OS.SelectObject(srcHdc, hMask);
         for (int y = 0, dp = 0; y < imgHeight; ++y) {
@@ -930,7 +950,7 @@
             }
         }
     }
-    (cast(byte*)pBits [0])[ 0 .. sizeInBytes] = srcData[];
+    (cast(byte*)pBits)[ 0 .. sizeInBytes] = srcData[];
     OS.SelectObject (srcHdc, oldSrcBitmap);
     OS.SelectObject (memHdc, oldMemBitmap);
     OS.DeleteObject (srcHdc);
@@ -959,8 +979,8 @@
     bmiHeader.biBitCount = cast(short)32;
     bmiHeader.biCompression = OS.BI_RGB;
     byte [] bmi = (cast(byte*)&bmiHeader)[ 0 .. BITMAPINFOHEADER.sizeof];
-    int [1] pBits;
-    auto memDib = OS.CreateDIBSection (null, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS, pBits.ptr, null, 0);
+    void* pBits;
+    auto memDib = OS.CreateDIBSection (null, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS, &pBits, null, 0);
     if (memDib is null) DWT.error (DWT.ERROR_NO_HANDLES);
     auto oldMemBitmap = OS.SelectObject (memHdc, memDib);
     BITMAP dibBM;
@@ -1001,7 +1021,7 @@
     OS.DeleteObject (srcHdc);
     OS.DeleteObject (memHdc);
     OS.ReleaseDC (null, hDC);
-    byte [] srcData = (cast(byte*)pBits[0])[ 0 .. sizeInBytes ].dup;
+    byte [] srcData = (cast(byte*)pBits)[ 0 .. sizeInBytes ].dup;
     if (alpha !is -1) {
         for (int y = 0, dp = 0; y < imgHeight; ++y) {
             for (int x = 0; x < imgWidth; ++x) {
@@ -1028,7 +1048,7 @@
             }
         }
     }
-    (cast(byte*)pBits[0])[ 0 .. sizeInBytes ] = srcData[];
+    (cast(byte*)pBits)[ 0 .. sizeInBytes ] = srcData[];
     return memDib;
 }
 
@@ -1112,10 +1132,11 @@
     return hMask;
 }
 
-static synchronized void deregister (Display display) {
-    static_this();
-    for (int i=0; i<Displays.length; i++) {
-        if (display is Displays [i]) Displays [i] = null;
+static void deregister (Display display) {
+    synchronized (Device.classinfo) {
+        for (int i=0; i<Displays.length; i++) {
+            if (display is Displays [i]) Displays [i] = null;
+        }
     }
 }
 
@@ -1294,6 +1315,7 @@
  */
 public Widget findWidget (HANDLE handle, int id) {
     checkDevice ();
+    //TODO - should ids be long
     Control control = getControl (handle);
     return control !is null ? control.findItem (cast(HANDLE) id) : null;
 }
@@ -1315,8 +1337,9 @@
  *
  * @since 3.3
  */
-public Widget findWidget (Widget widget, int id) {
+public Widget findWidget (Widget widget, int /*long*/ id) {
     checkDevice ();
+    //TODO - should ids be long
     if (cast(Control)widget) {
         return findWidget ((cast(Control) widget).handle, id);
     }
@@ -1329,14 +1352,16 @@
 }
 
 int foregroundIdleProc (int code, int wParam, int lParam) {
-    if (runMessages) {
-        if (code >= 0) {
-            if (getMessageCount () !is 0) {
-                if (runMessagesInIdle) {
+    if (code >= 0) {
+        if (runMessages && getMessageCount () !is 0) {
+            if (runMessagesInIdle) {
+                if (runMessagesInMessageProc) {
                     OS.PostMessage (hwndMessage, SWT_RUNASYNC, 0, 0);
+                } else {
+                    runAsyncMessages (false);
                 }
-                wakeThread ();
             }
+            wakeThread ();
         }
     }
     return OS.CallNextHookEx (idleHook, code, wParam, lParam);
@@ -1352,15 +1377,17 @@
  * @param thread the user-interface thread
  * @return the display for the given thread
  */
-public static synchronized Display findDisplay (Thread thread) {
+public static Display findDisplay (Thread thread) {
     static_this();
-    for (int i=0; i<Displays.length; i++) {
-        Display display = Displays [i];
-        if (display !is null && display.thread is thread) {
-            return display;
+    synchronized (Device.classinfo) {
+        for (int i=0; i<Displays.length; i++) {
+            Display display = Displays [i];
+            if (display !is null && display.thread is thread) {
+                return display;
+            }
         }
+        return null;
     }
-    return null;
 }
 
 /**
@@ -1382,7 +1409,8 @@
 }
 
 /**
- * Returns a rectangle describing the receiver's size and location.
+ * Returns a rectangle describing the receiver's size and location. Note that
+ * on multi-monitor systems the origin can be negative.
  *
  * @return the bounding rectangle
  *
@@ -1412,7 +1440,7 @@
  *
  * @return the current display
  */
-public static synchronized Display getCurrent () {
+public static Display getCurrent () {
     static_this();
     return findDisplay (Thread.getThis ());
 }
@@ -1421,12 +1449,11 @@
     switch (type) {
         case DWT.MouseDown:
             int doubleClick = OS.GetDoubleClickTime ();
-            //if (clickRect is null) clickRect = new RECT ();
+            if (clickRect is null) clickRect = new RECT ();
             int deltaTime = Math.abs (lastTime - getLastEventTime ());
             POINT pt;
-            pt.x = cast(short) (lParam & 0xFFFF);
-            pt.y = cast(short) (lParam >> 16);
-            if (lastClickHwnd is hwnd && lastButton is button && (deltaTime <= doubleClick) && OS.PtInRect (&clickRect, pt)) {
+            OS.POINTSTOPOINT (pt, lParam);
+            if (lastClickHwnd is hwnd && lastButton is button && (deltaTime <= doubleClick) && OS.PtInRect (clickRect, pt)) {
                 clickCount++;
             } else {
                 clickCount = 1;
@@ -1438,8 +1465,8 @@
             lastTime = getLastEventTime ();
             int xInset = OS.GetSystemMetrics (OS.SM_CXDOUBLECLK) / 2;
             int yInset = OS.GetSystemMetrics (OS.SM_CYDOUBLECLK) / 2;
-            int x = cast(short) (lParam & 0xFFFF), y = cast(short) (lParam >> 16);
-            OS.SetRect (&clickRect, x - xInset, y - yInset, x + xInset, y + yInset);
+            int x = OS.GET_X_LPARAM (lParam), y = OS.GET_Y_LPARAM (lParam);
+            OS.SetRect (clickRect, x - xInset, y - yInset, x + xInset, y + yInset);
             //FALL THROUGH
         case DWT.MouseUp:
             return clickCount;
@@ -1489,7 +1516,7 @@
     static if (USE_PROPERTY) {
         index = cast(int) OS.GetProp (handle, cast(wchar*)SWT_OBJECT_INDEX) - 1;
     } else {
-        index = OS.GetWindowLong (handle, OS.GWL_USERDATA) - 1;
+        index = OS.GetWindowLongPtr (handle, OS.GWLP_USERDATA) - 1;
     }
     if (0 <= index && index < controlTable.length) {
         Control control = controlTable [index];
@@ -1572,10 +1599,12 @@
  *
  * @return the default display
  */
-public static synchronized Display getDefault () {
+public static Display getDefault () {
     static_this();
-    if (Default is null) Default = new Display ();
-    return Default;
+    synchronized (Device.classinfo) {
+        if (Default is null) Default = new Display ();
+        return Default;
+    }
 }
 
 //PORTING_TODO
@@ -1616,6 +1645,9 @@
     if (key ==/*eq*/RUN_MESSAGES_IN_IDLE_KEY) {
         return new ValueWrapperBool(runMessagesInIdle);
     }
+    if (key.equals (RUN_MESSAGES_IN_MESSAGE_PROC_KEY)) {
+        return new Boolean (runMessagesInMessageProc);
+    }
     if (keys.length is 0) return null;
     for (int i=0; i<keys.length; i++) {
         if (keys [i] ==/*eq*/key) return values [i];
@@ -1967,9 +1999,8 @@
     return null;
 }
 
-Shell getModalDialogShell () {
-    if (modalDialogShell !is null && modalDialogShell.isDisposed ()) modalDialogShell = null;
-    return modalDialogShell;
+Dialog getModalDialog () {
+    return modalDialog;
 }
 
 /**
@@ -2012,9 +2043,9 @@
         //embeddedCallback = new Callback (this, "embeddedProc", 4); //$NON-NLS-1$
         //embeddedProc_ = embeddedCallback.getAddress ();
         //if (embeddedProc_ is 0) error (DWT.ERROR_NO_MORE_CALLBACKS);
-        OS.SetWindowLong (embeddedHwnd, OS.GWL_WNDPROC, cast(int) &embeddedFunc);
+        OS.SetWindowLongPtr (embeddedHwnd, OS.GWLP_WNDPROC, cast(LONG_PTR) &embeddedFunc);
     }
-    if (code >= 0 && wParam !is OS.PM_NOREMOVE) {
+    if (code >= 0 && (wParam & OS.PM_REMOVE) !is 0) {
         MSG* msg = cast(MSG*)lParam;
         switch (msg.message) {
             case OS.WM_KEYDOWN:
@@ -2167,6 +2198,23 @@
 }
 
 /**
+ * Gets the synchronizer used by the display.
+ *
+ * @return the receiver's synchronizer
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.4
+ */
+public Synchronizer getSynchronizer () {
+    checkDevice ();
+    return synchronizer;
+}
+
+/**
  * Returns the thread that has invoked <code>syncExec</code>
  * or null if no such runnable is currently being invoked by
  * the user-interface thread.
@@ -2182,8 +2230,10 @@
  * </ul>
  */
 public Thread getSyncThread () {
-    if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED);
-    return synchronizer.syncThread;
+    synchronized (Device.classinfo) {
+        if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED);
+        return synchronizer.syncThread;
+    }
 }
 
 /**
@@ -2414,8 +2464,10 @@
  * </ul>
  */
 public Thread getThread () {
-    if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED);
-    return thread;
+    synchronized (Device.classinfo) {
+        if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED);
+        return thread;
+    }
 }
 
 HTHEME hButtonTheme () {
@@ -2475,7 +2527,7 @@
             data.style |= DWT.LEFT_TO_RIGHT;
         }
         data.device = this;
-        data.hFont = getSystemFont ().handle;
+        data.font = getSystemFont ();
     }
     return hDC;
 }
@@ -2513,6 +2565,29 @@
     lpWndClass.lpfnWndProc = &windowProcFunc;
     lpWndClass.style = OS.CS_BYTEALIGNWINDOW | OS.CS_DBLCLKS;
     lpWndClass.hCursor = OS.LoadCursor (null, cast(wchar*)OS.IDC_ARROW);
+
+
+    //DWT_TODO: Check if this can be disabled for DWT
+    /+
+    /*
+    * Set the default icon for the window class to IDI_APPLICATION.
+    * This is not necessary for native Windows applications but
+    * versions of Java starting at JDK 1.6 set the icon in the
+    * executable instead of leaving the default.
+    */
+    if (!OS.IsWinCE && Library.JAVA_VERSION >= Library.JAVA_VERSION (1, 6, 0)) {
+        TCHAR[] lpszFile = NewTCHARs (0, OS.MAX_PATH);
+        while (OS.GetModuleFileName (0, lpszFile.ptr, lpszFile.length) is lpszFile.length) {
+            lpszFile = NewTCHARs (0, lpszFile.length + OS.MAX_PATH);
+        }
+        if (OS.ExtractIconEx (lpszFile.ptr, -1, null, null, 1) !is 0) {
+            String fileName = TCHARzToStr( lpszFile.ptr );
+            if (fileName.endsWith ("java.exe") || fileName.endsWith ("javaw.exe")) { //$NON-NLS-1$ //$NON-NLS-2$
+                lpWndClass.hIcon = OS.LoadIcon (0, OS.IDI_APPLICATION);
+            }
+        }
+    }
+    +/
     int byteCount = windowClass_.length * TCHAR.sizeof;
     lpWndClass.lpszClassName = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
     OS.MoveMemory (lpWndClass.lpszClassName, windowClass_.ptr, byteCount);
@@ -2520,7 +2595,9 @@
     OS.HeapFree (hHeap, 0, lpWndClass.lpszClassName);
 
     /* Register the DWT drop shadow window class */
-    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 1)) lpWndClass.style |= OS.CS_DROPSHADOW;
+    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 1)) {
+        lpWndClass.style |= OS.CS_DROPSHADOW;
+    }
     byteCount = windowShadowClass.length * TCHAR.sizeof;
     lpWndClass.lpszClassName = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
     OS.MoveMemory (lpWndClass.lpszClassName, windowShadowClass.ptr, byteCount);
@@ -2540,7 +2617,7 @@
     //messageCallback = new Callback (this, "messageProc", 4); //$NON-NLS-1$
     //messageProc_ = messageCallback.getAddress ();
     //if (messageProc_ is 0) error (DWT.ERROR_NO_MORE_CALLBACKS);
-    OS.SetWindowLong (hwndMessage, OS.GWL_WNDPROC, cast(int) &messageProcFunc);
+    OS.SetWindowLongPtr (hwndMessage, OS.GWLP_WNDPROC, cast(LONG_PTR) &messageProcFunc);
 
     /* Create the filter hook */
     static if (!OS.IsWinCE) {
@@ -2561,6 +2638,7 @@
     /* Register custom messages message */
     SWT_TASKBARCREATED = OS.RegisterWindowMessage (StrToTCHARz ( "TaskbarCreated" ));
     SWT_RESTORECARET = OS.RegisterWindowMessage (StrToTCHARz ( "SWT_RESTORECARET"));
+    DI_GETDRAGIMAGE = OS.RegisterWindowMessage (StrToTCHARz ( "ShellGetDragImage")); //$NON-NLS-1$
 
     /* Initialize OLE */
     static if (!OS.IsWinCE) OS.OleInitialize (null);
@@ -2988,9 +3066,10 @@
             */
             if (wParam !is 0) {
                 if (!isXMouseActive ()) {
-                    if (modalDialogShell !is null && modalDialogShell.isDisposed ()) modalDialogShell = null;
-                    Shell modal = modalDialogShell !is null ? modalDialogShell : getModalShell ();
-                    if (modal !is null) {
+                    auto hwndActive = OS.GetActiveWindow ();
+                    if (hwndActive !is null && OS.IsWindowEnabled (hwndActive)) break;
+                    Shell modal = modalDialog !is null ? modalDialog.parent : getModalShell ();
+                    if (modal !is null && !modal.isDisposed ()) {
                         auto hwndModal = modal.handle;
                         if (OS.IsWindowEnabled (hwndModal)) {
                             modal.bringToTop ();
@@ -3017,7 +3096,8 @@
                 * to run.  In order to avoid running code after the display
                 * has been disposed, exit from Java.
                 */
-                System.exit (0);
+                /* This code is intentionally commented */
+//              System.exit (0);
             }
             break;
         }
@@ -3027,7 +3107,15 @@
             if (!event.doit) return 0;
             break;
         }
+        case OS.WM_DWMCOLORIZATIONCOLORCHANGED: {
+            OS.SetTimer (hwndMessage, SETTINGS_ID, SETTINGS_DELAY, null);
+            break;
+        }
         case OS.WM_SETTINGCHANGE: {
+            if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+                OS.SetTimer (hwndMessage, SETTINGS_ID, SETTINGS_DELAY, null);
+                break;
+            }
             switch (wParam) {
                 case 0:
                 case 1:
@@ -3107,9 +3195,10 @@
 int msgFilterProc (int code, int wParam, int lParam) {
     switch (code) {
         case OS.MSGF_COMMCTRL_BEGINDRAG: {
-            if (!runDragDrop) {
-                hookMsg = *cast(MSG*)lParam;
+            if (!runDragDrop && !dragCancelled) {
+                *hookMsg = *cast(MSG*)lParam;
                 if (hookMsg.message is OS.WM_MOUSEMOVE) {
+                    dragCancelled = true;
                     OS.SendMessage (hookMsg.hwnd, OS.WM_CANCELMODE, 0, 0);
                 }
             }
@@ -3131,7 +3220,7 @@
         case OS.MSGF_SCROLLBAR:
         case OS.MSGF_SIZE: {
             if (runMessages) {
-                hookMsg = *cast(MSG*)lParam;
+                *hookMsg = *cast(MSG*)lParam;
                 if (hookMsg.message is OS.WM_NULL) {
                     MSG msg;
                     int flags = OS.PM_NOREMOVE | OS.PM_NOYIELD | OS.PM_QS_INPUT | OS.PM_QS_POSTMESSAGE;
@@ -3224,118 +3313,120 @@
  *
  */
 public bool post (Event event) {
-    if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED);
-    if (event is null) error (DWT.ERROR_NULL_ARGUMENT);
-    int type = event.type;
-    switch (type){
-        case DWT.KeyDown:
-        case DWT.KeyUp: {
+    synchronized (Device.classinfo) {
+        if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED);
+        if (event is null) error (DWT.ERROR_NULL_ARGUMENT);
+        int type = event.type;
+        switch (type){
+            case DWT.KeyDown:
+            case DWT.KeyUp: {
             KEYBDINPUT inputs;
             inputs.wVk = cast(short) untranslateKey (event.keyCode);
-            if (inputs.wVk is 0) {
-                char key = event.character;
-                switch (key) {
-                    case DWT.BS: inputs.wVk = cast(short) OS.VK_BACK; break;
-                    case DWT.CR: inputs.wVk = cast(short) OS.VK_RETURN; break;
-                    case DWT.DEL: inputs.wVk = cast(short) OS.VK_DELETE; break;
-                    case DWT.ESC: inputs.wVk = cast(short) OS.VK_ESCAPE; break;
-                    case DWT.TAB: inputs.wVk = cast(short) OS.VK_TAB; break;
-                    /*
-                    * Since there is no LF key on the keyboard, do not attempt
-                    * to map LF to CR or attempt to post an LF key.
-                    */
-//                  case DWT.LF: inputs.wVk = cast(short) OS.VK_RETURN; break;
-                    case DWT.LF: return false;
-                    default: {
-                        static if (OS.IsWinCE) {
-                            inputs.wVk = cast(int)OS.CharUpper (cast(wchar*) key);
-                        } else {
-                            inputs.wVk = OS.VkKeyScan (cast(short) wcsToMbcs (key, 0));
-                            if (inputs.wVk is -1) return false;
-                            inputs.wVk &= 0xFF;
+                if (inputs.wVk is 0) {
+                    char key = event.character;
+                    switch (key) {
+                        case DWT.BS: inputs.wVk = cast(short) OS.VK_BACK; break;
+                        case DWT.CR: inputs.wVk = cast(short) OS.VK_RETURN; break;
+                        case DWT.DEL: inputs.wVk = cast(short) OS.VK_DELETE; break;
+                        case DWT.ESC: inputs.wVk = cast(short) OS.VK_ESCAPE; break;
+                        case DWT.TAB: inputs.wVk = cast(short) OS.VK_TAB; break;
+                        /*
+                        * Since there is no LF key on the keyboard, do not attempt
+                        * to map LF to CR or attempt to post an LF key.
+                        */
+//                      case DWT.LF: inputs.wVk = cast(short) OS.VK_RETURN; break;
+                        case DWT.LF: return false;
+                        default: {
+                            static if (OS.IsWinCE) {
+                                inputs.wVk = cast(int)OS.CharUpper (cast(wchar*) key);
+                            } else {
+                                inputs.wVk = OS.VkKeyScan (cast(short) wcsToMbcs (key, 0));
+                                if (inputs.wVk is -1) return false;
+                                inputs.wVk &= 0xFF;
+                            }
                         }
                     }
                 }
-            }
-            inputs.dwFlags = type is DWT.KeyUp ? OS.KEYEVENTF_KEYUP : 0;
+                inputs.dwFlags = type is DWT.KeyUp ? OS.KEYEVENTF_KEYUP : 0;
             auto hHeap = OS.GetProcessHeap ();
             auto pInputs = cast(INPUT*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, INPUT.sizeof);
             pInputs.type = OS.INPUT_KEYBOARD;
-            pInputs.ki = inputs;
-            //OS.MoveMemory (pInputs + 4, inputs, KEYBDINPUT.sizeof);
-            bool result = OS.SendInput (1, pInputs, INPUT.sizeof) !is 0;
-            OS.HeapFree (hHeap, 0, pInputs);
-            return result;
-        }
-        case DWT.MouseDown:
-        case DWT.MouseMove:
-        case DWT.MouseUp:
-        case DWT.MouseWheel: {
-            MOUSEINPUT inputs;
-            if (type is DWT.MouseMove){
-                inputs.dwFlags = OS.MOUSEEVENTF_MOVE | OS.MOUSEEVENTF_ABSOLUTE;
-                int x= 0, y = 0, width = 0, height = 0;
-                if (OS.WIN32_VERSION >= OS.VERSION (5, 0)) {
-                    inputs.dwFlags |= OS.MOUSEEVENTF_VIRTUALDESK;
-                    x = OS.GetSystemMetrics (OS.SM_XVIRTUALSCREEN);
-                    y = OS.GetSystemMetrics (OS.SM_YVIRTUALSCREEN);
-                    width = OS.GetSystemMetrics (OS.SM_CXVIRTUALSCREEN);
-                    height = OS.GetSystemMetrics (OS.SM_CYVIRTUALSCREEN);
+                //TODO - DWORD type of INPUT structure aligned to 8 bytes on 64 bit
+                pInputs.ki = inputs;
+                //OS.MoveMemory (pInputs + 4, inputs, KEYBDINPUT.sizeof);
+                bool result = OS.SendInput (1, pInputs, INPUT.sizeof) !is 0;
+                OS.HeapFree (hHeap, 0, pInputs);
+                return result;
+            }
+            case DWT.MouseDown:
+            case DWT.MouseMove:
+            case DWT.MouseUp:
+            case DWT.MouseWheel: {
+                MOUSEINPUT inputs;
+                if (type is DWT.MouseMove){
+                    inputs.dwFlags = OS.MOUSEEVENTF_MOVE | OS.MOUSEEVENTF_ABSOLUTE;
+                    int x= 0, y = 0, width = 0, height = 0;
+                    if (OS.WIN32_VERSION >= OS.VERSION (5, 0)) {
+                        inputs.dwFlags |= OS.MOUSEEVENTF_VIRTUALDESK;
+                        x = OS.GetSystemMetrics (OS.SM_XVIRTUALSCREEN);
+                        y = OS.GetSystemMetrics (OS.SM_YVIRTUALSCREEN);
+                        width = OS.GetSystemMetrics (OS.SM_CXVIRTUALSCREEN);
+                        height = OS.GetSystemMetrics (OS.SM_CYVIRTUALSCREEN);
+                    } else {
+                        width = OS.GetSystemMetrics (OS.SM_CXSCREEN);
+                        height = OS.GetSystemMetrics (OS.SM_CYSCREEN);
+                    }
+                    inputs.dx = ((event.x - x) * 65535 + width - 2) / (width - 1);
+                    inputs.dy = ((event.y - y) * 65535 + height - 2) / (height - 1);
                 } else {
-                    width = OS.GetSystemMetrics (OS.SM_CXSCREEN);
-                    height = OS.GetSystemMetrics (OS.SM_CYSCREEN);
-                }
-                inputs.dx = ((event.x - x) * 65535 + width - 2) / (width - 1);
-                inputs.dy = ((event.y - y) * 65535 + height - 2) / (height - 1);
-            } else {
-                if (type is DWT.MouseWheel) {
-                    if (OS.WIN32_VERSION < OS.VERSION (5, 0)) return false;
-                    inputs.dwFlags = OS.MOUSEEVENTF_WHEEL;
-                    switch (event.detail) {
-                        case DWT.SCROLL_PAGE:
-                            inputs.mouseData = event.count * OS.WHEEL_DELTA;
-                            break;
-                        case DWT.SCROLL_LINE:
-                            int value;
-                            OS.SystemParametersInfo (OS.SPI_GETWHEELSCROLLLINES, 0, &value, 0);
-                            inputs.mouseData = event.count * OS.WHEEL_DELTA / value;
-                            break;
-                        default: return false;
-                    }
-                } else {
-                    switch (event.button) {
-                        case 1: inputs.dwFlags = type is DWT.MouseDown ? OS.MOUSEEVENTF_LEFTDOWN : OS.MOUSEEVENTF_LEFTUP; break;
-                        case 2: inputs.dwFlags = type is DWT.MouseDown ? OS.MOUSEEVENTF_MIDDLEDOWN : OS.MOUSEEVENTF_MIDDLEUP; break;
-                        case 3: inputs.dwFlags = type is DWT.MouseDown ? OS.MOUSEEVENTF_RIGHTDOWN : OS.MOUSEEVENTF_RIGHTUP; break;
-                        case 4: {
-                            if (OS.WIN32_VERSION < OS.VERSION (5, 0)) return false;
-                            inputs.dwFlags = type is DWT.MouseDown ? OS.MOUSEEVENTF_XDOWN : OS.MOUSEEVENTF_XUP;
-                            inputs.mouseData = OS.XBUTTON1;
-                            break;
+                    if (type is DWT.MouseWheel) {
+                        if (OS.WIN32_VERSION < OS.VERSION (5, 0)) return false;
+                        inputs.dwFlags = OS.MOUSEEVENTF_WHEEL;
+                        switch (event.detail) {
+                            case DWT.SCROLL_PAGE:
+                                inputs.mouseData = event.count * OS.WHEEL_DELTA;
+                                break;
+                            case DWT.SCROLL_LINE:
+                                int value;
+                                OS.SystemParametersInfo (OS.SPI_GETWHEELSCROLLLINES, 0, &value, 0);
+                                inputs.mouseData = event.count * OS.WHEEL_DELTA / value;
+                                break;
+                            default: return false;
                         }
-                        case 5: {
-                            if (OS.WIN32_VERSION < OS.VERSION (5, 0)) return false;
-                            inputs.dwFlags = type is DWT.MouseDown ? OS.MOUSEEVENTF_XDOWN : OS.MOUSEEVENTF_XUP;
-                            inputs.mouseData = OS.XBUTTON2;
-                            break;
+                    } else {
+                        switch (event.button) {
+                            case 1: inputs.dwFlags = type is DWT.MouseDown ? OS.MOUSEEVENTF_LEFTDOWN : OS.MOUSEEVENTF_LEFTUP; break;
+                            case 2: inputs.dwFlags = type is DWT.MouseDown ? OS.MOUSEEVENTF_MIDDLEDOWN : OS.MOUSEEVENTF_MIDDLEUP; break;
+                            case 3: inputs.dwFlags = type is DWT.MouseDown ? OS.MOUSEEVENTF_RIGHTDOWN : OS.MOUSEEVENTF_RIGHTUP; break;
+                            case 4: {
+                                if (OS.WIN32_VERSION < OS.VERSION (5, 0)) return false;
+                                inputs.dwFlags = type is DWT.MouseDown ? OS.MOUSEEVENTF_XDOWN : OS.MOUSEEVENTF_XUP;
+                                inputs.mouseData = OS.XBUTTON1;
+                                break;
+                            }
+                            case 5: {
+                                if (OS.WIN32_VERSION < OS.VERSION (5, 0)) return false;
+                                inputs.dwFlags = type is DWT.MouseDown ? OS.MOUSEEVENTF_XDOWN : OS.MOUSEEVENTF_XUP;
+                                inputs.mouseData = OS.XBUTTON2;
+                                break;
+                            }
+                            default: return false;
                         }
-                        default: return false;
                     }
                 }
+                auto hHeap = OS.GetProcessHeap ();
+                auto pInputs = cast(INPUT*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, INPUT.sizeof);
+                pInputs.type = OS.INPUT_MOUSE;
+                //TODO - DWORD type of INPUT structure aligned to 8 bytes on 64 bit
+                pInputs.mi = inputs;
+                bool result = OS.SendInput (1, pInputs, INPUT.sizeof) !is 0;
+                OS.HeapFree (hHeap, 0, pInputs);
+                return result;
             }
-            auto hHeap = OS.GetProcessHeap ();
-            auto pInputs = cast(INPUT*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, INPUT.sizeof);
-            pInputs.type = OS.INPUT_MOUSE;
-            //OS.MoveMemory(pInputs, [OS.INPUT_MOUSE], 4);
-            pInputs.mi = inputs;
-            //OS.MoveMemory (pInputs + 4, inputs, MOUSEINPUT.sizeof);
-            bool result = OS.SendInput (1, pInputs, INPUT.sizeof) !is 0;
-            OS.HeapFree (hHeap, 0, pInputs);
-            return result;
+        default:
         }
-        default:
+        return false;
     }
-    return false;
 }
 
 void postEvent (Event event) {
@@ -3389,10 +3480,10 @@
     lpStartupInfo = null;
     drawMenuBars ();
     runPopups ();
-    if (OS.PeekMessage (&msg, null, 0, 0, OS.PM_REMOVE)) {
-        if (!filterMessage (&msg)) {
-            OS.TranslateMessage (&msg);
-            OS.DispatchMessage (&msg);
+    if (OS.PeekMessage (msg, null, 0, 0, OS.PM_REMOVE)) {
+        if (!filterMessage (msg)) {
+            OS.TranslateMessage (msg);
+            OS.DispatchMessage (msg);
         }
         runDeferredEvents ();
         return true;
@@ -3400,18 +3491,20 @@
     return runMessages && runAsyncMessages (false);
 }
 
-static synchronized void register (Display display) {
+static void register (Display display) {
     static_this();
-    for (int i=0; i<Displays.length; i++) {
-        if (Displays [i] is null) {
-            Displays [i] = display;
-            return;
+    synchronized (Device.classinfo) {
+        for (int i=0; i<Displays.length; i++) {
+            if (Displays [i] is null) {
+                Displays [i] = display;
+                return;
+            }
         }
+        Display [] newDisplays = new Display [Displays.length + 4];
+        System.arraycopy (Displays, 0, newDisplays, 0, Displays.length);
+        newDisplays [Displays.length] = display;
+        Displays = newDisplays;
     }
-    Display [] newDisplays = new Display [Displays.length + 4];
-    System.arraycopy (Displays, 0, newDisplays, 0, Displays.length);
-    newDisplays [Displays.length] = display;
-    Displays = newDisplays;
 }
 
 /**
@@ -3563,18 +3656,31 @@
 
     /* Release references */
     thread = null;
-    //msg = null;
+    msg = null;
+    hookMsg = null;
     //keyboard = null;
-    modalDialogShell = null;
+    modalDialog = null;
     modalShells = null;
     data = null;
     keys = null;
     values = null;
     bars = popups = null;
     indexTable = null;
+    timerIds = null;
     controlTable = null;
     lastControl = lastGetControl = lastHittestControl = null;
     imageList = toolImageList = toolHotImageList = toolDisabledImageList = null;
+    timerList = null;
+    tableBuffer = null;
+    columnVisible = null;
+    eventTable = filterTable = null;
+    items = null;
+    clickRect = null;
+    hdr = null;
+    plvfi = null;
+
+    /* Release handles */
+    threadId = 0;
 }
 
 void releaseImageList (ImageList list) {
@@ -3731,16 +3837,14 @@
     static if (USE_PROPERTY) {
         index = cast(int)OS.RemoveProp (handle, cast(wchar*)SWT_OBJECT_INDEX) - 1;
     } else {
-        index = OS.GetWindowLong (handle, OS.GWL_USERDATA) - 1;
+        index = OS.GetWindowLongPtr (handle, OS.GWLP_USERDATA) - 1;
+        OS.SetWindowLongPtr (handle, OS.GWLP_USERDATA, 0);
     }
     if (0 <= index && index < controlTable.length) {
         control = controlTable [index];
         controlTable [index] = null;
         indexTable [index] = freeSlot;
         freeSlot = index;
-        if (!USE_PROPERTY) {
-            OS.SetWindowLong (handle, OS.GWL_USERDATA, 0);
-        }
     }
     return control;
 }
@@ -3838,7 +3942,7 @@
     }
 }
 
-bool runTimer (int id) {
+bool runTimer (int /*long*/ id) {
     if (timerList !is null && timerIds !is null) {
         int index = 0;
         while (index <timerIds.length) {
@@ -3999,6 +4103,11 @@
         runMessagesInIdle = data !is null && data.value;
         return;
     }
+    if (key.equals (RUN_MESSAGES_IN_MESSAGE_PROC_KEY)) {
+        Boolean data = cast(Boolean) value;
+        runMessagesInMessageProc = data !is null && data.booleanValue ();
+        return;
+    }
 
     /* Remove the key/value pair */
     if (value is null) {
@@ -4086,9 +4195,8 @@
     /* Do nothing */
 }
 
-void setModalDialogShell (Shell modalDailog) {
-    if (modalDialogShell !is null && modalDialogShell.isDisposed ()) modalDialogShell = null;
-    this.modalDialogShell = modalDailog;
+void setModalDialog (Dialog modalDailog) {
+    this.modalDialog = modalDailog;
     Shell [] shells = getShells ();
     for (int i=0; i<shells.length; i++) shells [i].updateModal ();
 }
@@ -4129,10 +4237,15 @@
 public void setSynchronizer (Synchronizer synchronizer) {
     checkDevice ();
     if (synchronizer is null) error (DWT.ERROR_NULL_ARGUMENT);
-    if (this.synchronizer !is null) {
-        this.synchronizer.runAsyncMessages(true);
+    if (synchronizer is this.synchronizer) return;
+    Synchronizer oldSynchronizer;
+    synchronized (Device.classinfo) {
+        oldSynchronizer = this.synchronizer;
+        this.synchronizer = synchronizer;
     }
-    this.synchronizer = synchronizer;
+    if (oldSynchronizer !is null) {
+        oldSynchronizer.runAsyncMessages(true);
+    }
 }
 
 int shiftedKey (int key) {
@@ -4200,7 +4313,11 @@
  * @see #asyncExec
  */
 public void syncExec (Runnable runnable) {
-    if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED);
+    Synchronizer synchronizer;
+    synchronized (Device.classinfo) {
+        if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED);
+        synchronizer = this.synchronizer;
+    }
     synchronizer.syncExec (runnable);
 }
 
@@ -4234,13 +4351,13 @@
     if (runnable is null) error (DWT.ERROR_NULL_ARGUMENT);
     assert( runnable );
     if (timerList is null) timerList = new Runnable [4];
-    if (timerIds is null) timerIds = new int [4];
+    if (timerIds is null) timerIds = new int /*long*/ [4];
     int index = 0;
     while (index < timerList.length) {
         if (timerList [index] is runnable) break;
         index++;
     }
-    int timerId = 0;
+    int /*long*/ timerId = 0;
     if (index !is timerList.length) {
         timerId = timerIds [index];
         if (milliseconds < 0) {
@@ -4261,7 +4378,7 @@
             Runnable [] newTimerList = new Runnable [timerList.length + 4];
             SimpleType!(Runnable).arraycopy (timerList, 0, newTimerList, 0, timerList.length);
             timerList = newTimerList;
-            int [] newTimerIds = new int [timerIds.length + 4];
+            int /*long*/ [] newTimerIds = new int /*long*/ [timerIds.length + 4];
             System.arraycopy (timerIds, 0, newTimerIds, 0, timerIds.length);
             timerIds = newTimerIds;
         }
@@ -4395,9 +4512,11 @@
  * @see #sleep
  */
 public void wake () {
-    if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED);
-    if (thread is Thread.getThis ()) return;
-    wakeThread ();
+    synchronized (Device.classinfo) {
+        if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED);
+        if (thread is Thread.getThis ()) return;
+        wakeThread ();
+    }
 }
 
 void wakeThread () {
@@ -4451,6 +4570,27 @@
 
 int windowProc (HWND hwnd, uint msg, uint wParam, int lParam) {
     /*
+    * Feature in Windows.  On Vista only, it is faster to
+    * compute and answer the data for the visible columns
+    * of a table when scrolling, rather than just return
+    * the data for each column when asked.
+    */
+    if (columnVisible !is null) {
+        if (msg is OS.WM_NOTIFY && hwndParent is hwnd) {
+            OS.MoveMemory (hdr, lParam, NMHDR.sizeof);
+            switch (hdr.code) {
+                case OS.LVN_GETDISPINFOA:
+                case OS.LVN_GETDISPINFOW: {
+                    OS.MoveMemory (plvfi, lParam, NMLVDISPINFO.sizeof);
+                    if (0 <= plvfi.item.iSubItem && plvfi.item.iSubItem < columnCount) {
+                        if (!columnVisible [plvfi.item.iSubItem]) return 0;
+                    }
+                    break;
+                }
+            }
+        }
+    }
+    /*
     * Bug in Adobe Reader 7.0.  For some reason, when Adobe
     * Reader 7.0 is deactivated from within Internet Explorer,
     * it sends thousands of consecutive WM_NCHITTEST messages
@@ -4477,7 +4617,7 @@
     static if (USE_PROPERTY) {
         index = cast(int)OS.GetProp (hwnd, cast(wchar*)SWT_OBJECT_INDEX) - 1;
     } else {
-        index = OS.GetWindowLong (hwnd, OS.GWL_USERDATA) - 1;
+        index = OS.GetWindowLongPtr (hwnd, OS.GWLP_USERDATA) - 1;
     }
     if (0 <= index && index < controlTable.length) {
         Control control = controlTable [index];
--- a/dwt/widgets/Event.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/Event.d	Sat May 17 17:34:28 2008 +0200
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2006 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
--- a/dwt/widgets/EventTable.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/EventTable.d	Sat May 17 17:34:28 2008 +0200
@@ -32,10 +32,28 @@
     int [] types;
     Listener [] listeners;
     int level;
+    static final int GROW_SIZE = 4;
+    
+public Listener [] getListeners (int eventType) {
+    if (types is null) return new Listener [0];
+    int count = 0;
+    for (int i=0; i<types.length; i++) {
+        if (types [i] is eventType) count++;
+    }
+    if (count is 0) return new Listener [0];
+    Listener [] result = new Listener [count];
+    count = 0;
+    for (int i=0; i<types.length; i++) {
+        if (types [i] is eventType) {
+            result [count++] = listeners [i];
+        }
+    }
+    return result;
+}
 
 public void hook (int eventType, Listener listener) {
-    if (types is null) types = new int [4];
-    if (listeners is null) listeners = new Listener [4];
+    if (types is null) types = new int [GROW_SIZE];
+    if (listeners is null) listeners = new Listener [GROW_SIZE];
     int length = types.length, index = length - 1;
     while (index >= 0) {
         if (types [index] !is 0) break;
@@ -43,10 +61,10 @@
     }
     index++;
     if (index is length) {
-        int [] newTypes = new int [length + 4];
+        int [] newTypes = new int [length + GROW_SIZE];
         System.arraycopy (types, 0, newTypes, 0, length);
         types = newTypes;
-        Listener [] newListeners = new Listener [length + 4];
+        Listener [] newListeners = new Listener [length + GROW_SIZE];
         SimpleType!(Listener).arraycopy (listeners, 0, newListeners, 0, length);
         listeners = newListeners;
     }
--- a/dwt/widgets/ExpandBar.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/ExpandBar.d	Sat May 17 17:34:28 2008 +0200
@@ -285,27 +285,34 @@
         int uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
         drawFocus = (uiState & OS.UISF_HIDEFOCUS) is 0;
     }
-    HFONT hCaptionFont, oldFont;
+    HFONT hCurrentFont, oldFont;
     if (hTheme is null) {
-        static if (!OS.IsWinCE ) {
-            if (hFont is null) {
+        if (hFont !is null) {
+            hCurrentFont = hFont;
+        } else {
+            if (!OS.IsWinCE) {
                 NONCLIENTMETRICS info;
                 info.cbSize = NONCLIENTMETRICS.sizeof;
                 if (OS.SystemParametersInfo (OS.SPI_GETNONCLIENTMETRICS, 0, &info, 0)) {
                     LOGFONT* logFont = &info.lfCaptionFont;
-                    hCaptionFont = OS.CreateFontIndirect (logFont);
-                    oldFont = OS.SelectObject (gc.handle, hCaptionFont);
+                    hCurrentFont = OS.CreateFontIndirect (logFont);
                 }
             }
         }
+        if (hCurrentFont !is null) {
+            oldFont = OS.SelectObject (gc.handle, hCurrentFont);
+        }
+        if (foreground !is -1) {
+            OS.SetTextColor (gc.handle, foreground);
+        }
     }
     for (int i = 0; i < itemCount; i++) {
         ExpandItem item = items[i];
         item.drawItem (gc, hTheme, clipRect, item is focusItem && drawFocus);
     }
-    if (hCaptionFont !is null) {
+    if (hCurrentFont !is null) {
         OS.SelectObject (gc.handle, oldFont);
-        OS.DeleteObject (hCaptionFont);
+        if (hCurrentFont !is hFont) OS.DeleteObject (hCurrentFont);
     }
 }
 
@@ -582,8 +589,44 @@
     layoutItems (index + 1, true);
 }
 
+void showFocus (bool up) {
+    RECT rect;
+    OS.GetClientRect (handle, &rect);
+    int height = rect.bottom - rect.top;
+    int updateY = 0;
+    if (up) {
+        if (focusItem.y < 0) {
+            updateY = Math.min (yCurrentScroll, -focusItem.y);
+        }
+    } else {
+        int itemHeight = focusItem.y + getBandHeight ();
+        if (focusItem.expanded) {
+            if (height >= getBandHeight () + focusItem.height) {
+                itemHeight += focusItem.height;
+            }
+        }
+        if (itemHeight > height) {
+            updateY = height - itemHeight;
+        }
+    }
+    if (updateY !is 0) {
+        yCurrentScroll = Math.max (0, yCurrentScroll - updateY);
+        if ((style & DWT.V_SCROLL) !is 0) {
+            SCROLLINFO info;
+            info.cbSize = SCROLLINFO.sizeof;
+            info.fMask = OS.SIF_POS;
+            info.nPos = yCurrentScroll;
+            OS.SetScrollInfo (handle, OS.SB_VERT, &info, true);
+        }
+        OS.ScrollWindowEx (handle, 0, updateY, null, null, null, null, OS.SW_SCROLLCHILDREN | OS.SW_INVALIDATE);
+        for (int i = 0; i < itemCount; i++) {
+            items [i].y += updateY;
+        }
+    }
+}
+
 override String windowClass () {
-    return display.windowClass();
+    return display.windowClass;
 }
 
 override int windowProc () {
@@ -610,6 +653,7 @@
                 focusItem.redraw (true);
                 focusItem = items [focusIndex - 1];
                 focusItem.redraw (true);
+                showFocus (true);
                 return LRESULT.ZERO;
             }
             break;
@@ -620,6 +664,7 @@
                 focusItem.redraw (true);
                 focusItem = items [focusIndex + 1];
                 focusItem.redraw (true);
+                showFocus (false);
                 return LRESULT.ZERO;
             }
             break;
@@ -630,18 +675,16 @@
 }
 
 override LRESULT WM_KILLFOCUS (int wParam, int lParam) {
-trc(__LINE__);
     LRESULT result = super.WM_KILLFOCUS (wParam, lParam);
     if (focusItem !is null) focusItem.redraw (true);
     return result;
 }
 
 override LRESULT WM_LBUTTONDOWN (int wParam, int lParam) {
-//trc(__LINE__);
     LRESULT result = super.WM_LBUTTONDOWN (wParam, lParam);
     if (result is LRESULT.ZERO) return result;
-    int x = cast(short) (lParam & 0xFFFF);
-    int y = cast(short) (lParam >> 16);
+    int x = OS.GET_X_LPARAM (lParam);
+    int y = OS.GET_Y_LPARAM (lParam);
     for (int i = 0; i < itemCount; i++) {
         ExpandItem item = items[i];
         bool hover = item.isHover (x, y);
@@ -660,8 +703,8 @@
     LRESULT result = super.WM_LBUTTONUP (wParam, lParam);
     if (result is LRESULT.ZERO) return result;
     if (focusItem is null) return result;
-    int x = cast(short) (lParam & 0xFFFF);
-    int y = cast(short) (lParam >> 16);
+    int x = OS.GET_X_LPARAM (lParam);
+    int y = OS.GET_Y_LPARAM (lParam);
     bool hover = focusItem.isHover (x, y);
     if (hover) {
         Event event = new Event ();
@@ -689,11 +732,10 @@
 }
 
 override LRESULT WM_MOUSEMOVE (int wParam, int lParam) {
-trc(__LINE__);
     LRESULT result = super.WM_MOUSEMOVE (wParam, lParam);
     if (result is LRESULT.ZERO) return result;
-    int x = cast(short) (lParam & 0xFFFF);
-    int y = cast(short) (lParam >> 16);
+    int x = OS.GET_X_LPARAM (lParam);
+    int y = OS.GET_Y_LPARAM (lParam);
     for (int i = 0; i < itemCount; i++) {
         ExpandItem item = items [i];
         bool hover = item.isHover (x, y);
@@ -753,7 +795,7 @@
 trc(__LINE__);
     LRESULT result = super.WM_SETCURSOR (wParam, lParam);
     if (result !is null) return result;
-    int hitTest = lParam & 0xFFFF;
+    int hitTest = cast(short) OS.LOWORD (lParam);
     if (hitTest is OS.HTCLIENT) {
         for (int i = 0; i < itemCount; i++) {
             ExpandItem item = items [i];
--- a/dwt/widgets/FileDialog.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/FileDialog.d	Sat May 17 17:34:28 2008 +0200
@@ -43,9 +43,24 @@
     String [] filterExtensions;
     String [] fileNames;
     String filterPath = "", fileName = "";
-    static final String FILTER = "*.*";
+    int filterIndex = 0;
+    bool overwrite = false;
+    static const String FILTER = "*.*";
     static int BUFFER_SIZE = 1024 * 32;
-    static bool USE_HOOK;
+    static bool USE_HOOK = true;
+    static this() {
+        /*
+        *  Feature in Vista.  When OFN_ENABLEHOOK is set in the
+        *  save or open file dialog,  Vista uses the old XP look
+        *  and feel.  OFN_ENABLEHOOK is used to grow the file
+        *  name buffer in a multi-select file dialog.  The fix
+        *  is to only use OFN_ENABLEHOOK when the buffer has
+        *  overrun.
+        */
+        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+            USE_HOOK = false;
+        }
+    }
 
 /**
  * Constructs a new instance of this class given only its parent.
@@ -61,7 +76,7 @@
  * </ul>
  */
 public this (Shell parent) {
-    this (parent, DWT.PRIMARY_MODAL);
+    this (parent, DWT.APPLICATION_MODAL);
 }
 
 /**
@@ -89,7 +104,7 @@
  * </ul>
  */
 public this (Shell parent, int style) {
-    super (parent, style);
+    super (parent, checkStyle (parent, style));
     checkSubclass ();
 }
 
@@ -125,6 +140,26 @@
 }
 
 /**
+ * Get the 0-based index of the file extension filter
+ * which was selected by the user, or -1 if no filter
+ * was selected.
+ * <p>
+ * This is an index into the FilterExtensions array and
+ * the FilterNames array.
+ * </p>
+ *
+ * @return index the file extension filter index
+ *
+ * @see #getFilterExtensions
+ * @see #getFilterNames
+ *
+ * @since 3.4
+ */
+public int getFilterIndex () {
+    return filterIndex;
+}
+
+/**
  * Returns the names that describe the filter extensions
  * which the dialog will use to filter the files it shows.
  *
@@ -147,6 +182,19 @@
     return filterPath;
 }
 
+/**
+ * Returns the flag that the dialog will use to
+ * determine whether to prompt the user for file
+ * overwrite if the selected file already exists.
+ *
+ * @return true if the dialog will prompt for file overwrite, false otherwise
+ *
+ * @since 3.4
+ */
+public bool getOverwrite () {
+    return overwrite;
+}
+
 private static extern(Windows) uint OFNHookProc (HWND hdlg, uint uiMsg, uint wParam, int lParam) {
     switch (uiMsg) {
         case OS.WM_NOTIFY:
@@ -193,7 +241,35 @@
 
     /* Get the owner HWND for the dialog */
     HWND hwndOwner;
-    if (parent !is null) hwndOwner = parent.handle;
+    auto hwndParent = parent.handle;
+
+    /*
+    * Feature in Windows.  There is no API to set the orientation of a
+    * file dialog.  It is always inherited from the parent.  The fix is
+    * to create a hidden parent and set the orientation in the hidden
+    * parent for the dialog to inherit.
+    */
+    bool enabled = false;
+    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION(4, 10)) {
+        int dialogOrientation = style & (DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT);
+        int parentOrientation = parent.style & (DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT);
+        if (dialogOrientation !is parentOrientation) {
+            int exStyle = OS.WS_EX_NOINHERITLAYOUT;
+            if (dialogOrientation is DWT.RIGHT_TO_LEFT) exStyle |= OS.WS_EX_LAYOUTRTL;
+            hwndOwner = OS.CreateWindowEx (
+                exStyle,
+                Shell.DialogClass.ptr,
+                null,
+                0,
+                OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
+                hwndParent,
+                null,
+                OS.GetModuleHandle (null),
+                null);
+            enabled = OS.IsWindowEnabled (hwndParent) !is 0;
+            if (enabled) OS.EnableWindow (hwndParent, false);
+        }
+    }
 
     /* Convert the title and copy it into lpstrTitle */
     if (title is null) title = "";
@@ -253,7 +329,8 @@
     OPENFILENAME struct_;
     struct_.lStructSize = OPENFILENAME.sizeof;
     struct_.Flags = OS.OFN_HIDEREADONLY | OS.OFN_NOCHANGEDIR;
-    //Callback callback = null;
+    bool save = (style & DWT.SAVE) !is 0;
+    if (save && overwrite) struct_.Flags |= OS.OFN_OVERWRITEPROMPT;
     if ((style & DWT.MULTI) !is 0) {
         struct_.Flags |= OS.OFN_ALLOWMULTISELECT | OS.OFN_EXPLORER;
         if (!OS.IsWinCE && USE_HOOK) {
@@ -271,7 +348,7 @@
     struct_.nMaxFile = nMaxFile;
     struct_.lpstrInitialDir = lpstrInitialDir;
     struct_.lpstrFilter = lpstrFilter;
-    struct_.nFilterIndex = 0;
+    struct_.nFilterIndex = filterIndex is 0 ? filterIndex : filterIndex + 1;
 
     /*
     * Set the default extension to an empty string.  If the
@@ -280,18 +357,17 @@
     * extension at the time that the dialog is closed.
     */
     TCHAR* lpstrDefExt;
-    bool save = (style & DWT.SAVE) !is 0;
     if (save) {
         lpstrDefExt = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, TCHAR.sizeof);
         struct_.lpstrDefExt = lpstrDefExt;
     }
 
     /* Make the parent shell be temporary modal */
-    Shell oldModal = null;
+    Dialog oldModal = null;
     Display display = parent.getDisplay ();
     if ((style & (DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL)) !is 0) {
-        oldModal = display.getModalDialogShell ();
-        display.setModalDialogShell (parent);
+        oldModal = display.getModalDialog ();
+        display.setModalDialog (this);
     }
 
     /*
@@ -327,7 +403,7 @@
 
     /* Clear the temporary dialog modal parent */
     if ((style & (DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL)) !is 0) {
-        display.setModalDialogShell (oldModal);
+        display.setModalDialog (oldModal);
     }
 
     /* Dispose the callback and reassign the buffer */
@@ -335,7 +411,7 @@
     lpstrFile = struct_.lpstrFile;
 
     /* Set the new path, file name and filter */
-    fileNames = new String [0];
+    fileNames = null;
     String fullPath = null;
     if (success) {
 
@@ -408,6 +484,7 @@
                 fileNames = newFileNames;
             }
         }
+        filterIndex = struct_.nFilterIndex - 1;
     }
 
     /* Free the memory that was allocated. */
@@ -417,6 +494,13 @@
     OS.HeapFree (hHeap, 0, lpstrTitle);
     if (lpstrDefExt !is null) OS.HeapFree (hHeap, 0, lpstrDefExt);
 
+    /* Destroy the BIDI orientation window */
+    if (hwndParent !is hwndOwner) {
+        if (enabled) OS.EnableWindow (hwndParent, true);
+        OS.SetActiveWindow (hwndParent);
+        OS.DestroyWindow (hwndOwner);
+    }
+
     /*
     * This code is intentionally commented.  On some
     * platforms, the owner window is repainted right
@@ -461,7 +545,27 @@
 }
 
 /**
- * Sets the the names that describe the filter extensions
+ * Set the 0-based index of the file extension filter
+ * which the dialog will use initially to filter the files
+ * it shows to the argument.
+ * <p>
+ * This is an index into the FilterExtensions array and
+ * the FilterNames array.
+ * </p>
+ *
+ * @param index the file extension filter index
+ *
+ * @see #setFilterExtensions
+ * @see #setFilterNames
+ *
+ * @since 3.4
+ */
+public void setFilterIndex (int index) {
+    filterIndex = index;
+}
+
+/**
+ * Sets the names that describe the filter extensions
  * which the dialog will use to filter the files it shows
  * to the argument, which may be null.
  * <p>
@@ -499,5 +603,17 @@
     filterPath = string;
 }
 
+/**
+ * Sets the flag that the dialog will use to
+ * determine whether to prompt the user for file
+ * overwrite if the selected file already exists.
+ *
+ * @param overwrite true if the dialog will prompt for file overwrite, false otherwise
+ *
+ * @since 3.4
+ */
+public void setOverwrite (bool overwrite) {
+    this.overwrite = overwrite;
+}
 }
 
--- a/dwt/widgets/FontDialog.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/FontDialog.d	Sat May 17 17:34:28 2008 +0200
@@ -58,7 +58,7 @@
  * </ul>
  */
 public this (Shell parent) {
-    this (parent, DWT.PRIMARY_MODAL);
+    this (parent, DWT.APPLICATION_MODAL);
 }
 
 /**
@@ -86,7 +86,7 @@
  * </ul>
  */
 public this (Shell parent, int style) {
-    super (parent, style);
+    super (parent, checkStyle (parent, style));
     checkSubclass ();
 }
 
@@ -145,8 +145,36 @@
     static if (OS.IsWinCE) DWT.error (DWT.ERROR_NOT_IMPLEMENTED);
 
     /* Get the owner HWND for the dialog */
-    HWND hwndOwner;
-    if (parent !is null) hwndOwner = parent.handle;
+    HWND hwndOwner = parent.handle;
+    auto hwndParent = parent.handle;
+
+    /*
+    * Feature in Windows.  There is no API to set the orientation of a
+    * font dialog.  It is always inherited from the parent.  The fix is
+    * to create a hidden parent and set the orientation in the hidden
+    * parent for the dialog to inherit.
+    */
+    bool enabled = false;
+    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION(4, 10)) {
+        int dialogOrientation = style & (DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT);
+        int parentOrientation = parent.style & (DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT);
+        if (dialogOrientation !is parentOrientation) {
+            int exStyle = OS.WS_EX_NOINHERITLAYOUT;
+            if (dialogOrientation is DWT.RIGHT_TO_LEFT) exStyle |= OS.WS_EX_LAYOUTRTL;
+            hwndOwner = OS.CreateWindowEx (
+                exStyle,
+                Shell.DialogClass.ptr,
+                null,
+                0,
+                OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
+                hwndParent,
+                null,
+                OS.GetModuleHandle (null),
+                null);
+            enabled = OS.IsWindowEnabled (hwndParent) !is 0;
+            if (enabled) OS.EnableWindow (hwndParent, false);
+        }
+    }
 
     /* Open the dialog */
     auto hHeap = OS.GetProcessHeap ();
@@ -175,12 +203,12 @@
     }
 
     /* Make the parent shell be temporary modal */
-    Shell oldModal = null;
+    Dialog oldModal = null;
     Display display = null;
     if ((style & (DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL)) !is 0) {
         display = parent.getDisplay ();
-        oldModal = display.getModalDialogShell ();
-        display.setModalDialogShell (parent);
+        oldModal = display.getModalDialog ();
+        display.setModalDialog (this);
     }
 
     /* Open the dialog */
@@ -188,7 +216,7 @@
 
     /* Clear the temporary dialog modal parent */
     if ((style & (DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL)) !is 0) {
-        display.setModalDialogShell (oldModal);
+        display.setModalDialog (oldModal);
     }
 
     /* Compute the result */
@@ -235,6 +263,13 @@
     /* Free the OS memory */
     if (lpLogFont !is null) OS.HeapFree (hHeap, 0, lpLogFont);
 
+    /* Destroy the BIDI orientation window */
+    if (hwndParent !is hwndOwner) {
+        if (enabled) OS.EnableWindow (hwndParent, true);
+        OS.SetActiveWindow (hwndParent);
+        OS.DestroyWindow (hwndOwner);
+    }
+
     /*
     * This code is intentionally commented.  On some
     * platforms, the owner window is repainted right
--- a/dwt/widgets/Group.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/Group.d	Sat May 17 17:34:28 2008 +0200
@@ -207,7 +207,8 @@
         OS.DrawText (hDC, buffer, -1, &rect, flags);
         if (newFont !is null) OS.SelectObject (hDC, oldFont);
         OS.ReleaseDC (handle, hDC);
-        size.x = Math.max (size.x, rect.right - rect.left + CLIENT_INSET * 6);
+        int offsetY = OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed () ? 0 : 1;
+        size.x = Math.max (size.x, rect.right - rect.left + CLIENT_INSET * 6 + offsetY);
     }
     return size;
 }
@@ -223,15 +224,27 @@
     OS.GetTextMetrics (hDC, &tm);
     if (newFont !is null) OS.SelectObject (hDC, oldFont);
     OS.ReleaseDC (handle, hDC);
+    int offsetY = OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed () ? 0 : 1;
     trim.x -= CLIENT_INSET;
-    trim.y -= tm.tmHeight;
+    trim.y -= tm.tmHeight + offsetY;
     trim.width += CLIENT_INSET * 2;
     trim.height += tm.tmHeight + CLIENT_INSET;
     return trim;
 }
 
 override void createHandle () {
+    /*
+    * Feature in Windows.  When a button is created,
+    * it clears the UI state for all controls in the
+    * shell by sending WM_CHANGEUISTATE with UIS_SET,
+    * UISF_HIDEACCEL and UISF_HIDEFOCUS to the parent.
+    * This is undocumented and unexpected.  The fix
+    * is to ignore the WM_CHANGEUISTATE, when sent
+    * from CreateWindowEx().
+    */
+    parent.state |= IGNORE_WM_CHANGEUISTATE;
     super.createHandle ();
+    parent.state &= ~IGNORE_WM_CHANGEUISTATE;
     state |= DRAW_BACKGROUND;
     state &= ~CANVAS;
 }
@@ -265,7 +278,8 @@
     OS.GetTextMetrics (hDC, &tm);
     if (newFont !is null) OS.SelectObject (hDC, oldFont);
     OS.ReleaseDC (handle, hDC);
-    int x = CLIENT_INSET, y = tm.tmHeight;
+    int offsetY = OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed () ? 0 : 1;
+    int x = CLIENT_INSET, y = tm.tmHeight + offsetY;
     int width = Math.max (0, rect.right - CLIENT_INSET * 2);
     int height = Math.max (0, rect.bottom - y - CLIENT_INSET);
     return new Rectangle (x, y, width, height);
@@ -406,7 +420,7 @@
     * allow children, answer HTCLIENT to allow mouse messages
     * to be delivered to the children.
     */
-    int code = callWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam);
+    int /*long*/ code = callWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam);
     if (code is OS.HTTRANSPARENT) code = OS.HTCLIENT;
     return new LRESULT (code);
 }
@@ -438,7 +452,7 @@
     */
     if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
         auto nSavedDC = OS.SaveDC (cast(HDC)wParam);
-        int code = callWindowProc (handle, OS.WM_PRINTCLIENT, wParam, lParam);
+        int /*long*/ code = callWindowProc (handle, OS.WM_PRINTCLIENT, wParam, lParam);
         OS.RestoreDC (cast(HDC)wParam, nSavedDC);
         return new LRESULT (code);
     }
@@ -467,7 +481,7 @@
     }
     if (redraw) {
         OS.InvalidateRect (handle, null, false);
-        int code = OS.DefWindowProc (handle, OS.WM_UPDATEUISTATE, wParam, lParam);
+        int /*long*/ code = OS.DefWindowProc (handle, OS.WM_UPDATEUISTATE, wParam, lParam);
         return new LRESULT (code);
     }
     return result;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/widgets/IME.d	Sat May 17 17:34:28 2008 +0200
@@ -0,0 +1,429 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+module dwt.widgets.IME;
+
+
+import dwt.DWT;
+import dwt.graphics.Color;
+import dwt.graphics.TextStyle;
+import dwt.internal.win32.OS;
+import dwt.internal.win32.WINTYPES;
+
+import dwt.widgets.Widget;
+import dwt.widgets.Canvas;
+import dwt.widgets.Event;
+import dwt.widgets.Display;
+
+import dwt.dwthelper.utils;
+
+/**
+ * TODO - JAVA DOC
+ *
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>(none)</dd>
+ * <dt><b>Events:</b></dt>
+ * <dd>(none)</dd>
+ * </dl>
+ * <p>
+ * .
+ * </p>
+ *
+ * @since 3.4
+ */
+
+public class IME : Widget {
+    Canvas parent;
+    int caretOffset;
+    int startOffset;
+    int commitCount;
+    String text;
+    int [] ranges;
+    TextStyle [] styles;
+
+    static const int WM_MSIME_MOUSE;
+
+    static byte [16] IID_ITfInputProcessorProfiles;
+    static byte [16] IID_ITfDisplayAttributeProvider;
+    static byte [16] CLSID_TF_InputProcessorProfiles;
+    static byte [16] GUID_TFCAT_TIP_KEYBOARD;
+    static this() {
+        WM_MSIME_MOUSE = OS.RegisterWindowMessage (StrToTCHARz ("MSIMEMouseOperation"));
+
+        OS.IIDFromString ("{1F02B6C5-7842-4EE6-8A0B-9A24183A95CA}\0"w.ptr, IID_ITfInputProcessorProfiles.ptr);
+        OS.IIDFromString ("{fee47777-163c-4769-996a-6e9c50ad8f54}\0"w.ptr, IID_ITfDisplayAttributeProvider.ptr);
+        OS.IIDFromString ("{33C53A50-F456-4884-B049-85FD643ECFED}\0"w.ptr, CLSID_TF_InputProcessorProfiles.ptr);
+        OS.IIDFromString ("{34745C63-B2F0-4784-8B67-5E12C8701A31}\0"w.ptr, GUID_TFCAT_TIP_KEYBOARD.ptr);
+    }
+
+    /* TextLayout has a copy of these constants */
+    static const int UNDERLINE_IME_DOT = 1 << 16;
+    static const int UNDERLINE_IME_DASH = 2 << 16;
+    static const int UNDERLINE_IME_THICK = 3 << 16;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+this () {
+}
+
+/**
+ *
+ * @see DWT
+ */
+public this (Canvas parent, int style) {
+    super (parent, style);
+    this.parent = parent;
+    createWidget ();
+}
+
+void createWidget () {
+    text = "";
+    startOffset = -1;
+    if (parent.getIME () is null) {
+        parent.setIME (this);
+    }
+}
+
+public int getCaretOffset () {
+    checkWidget ();
+    return startOffset + caretOffset;
+}
+
+public int getCommitCount () {
+    checkWidget ();
+    return commitCount;
+}
+
+public int getCompositionOffset () {
+    checkWidget ();
+    return startOffset;
+}
+
+TF_DISPLAYATTRIBUTE* getDisplayAttribute (short langid, int attInfo) {
+    void* pProfiles;
+    int hr = OS.CoCreateInstance (CLSID_TF_InputProcessorProfiles.ptr, null, OS.CLSCTX_INPROC_SERVER, IID_ITfInputProcessorProfiles.ptr, &pProfiles);
+    TF_DISPLAYATTRIBUTE* pda;
+    if (hr is OS.S_OK) {
+        byte [16] pclsid;
+        byte [16] pguidProfile;
+        /* pProfiles.GetDefaultLanguageProfile () */
+        hr = OS.VtblCall (8, pProfiles, cast(int)langid, cast(int)GUID_TFCAT_TIP_KEYBOARD.ptr, cast(int)pclsid.ptr, cast(int)pguidProfile.ptr);
+        if (hr is OS.S_OK) {
+            void* pProvider;
+            hr = OS.CoCreateInstance (pclsid.ptr, null, OS.CLSCTX_INPROC_SERVER, IID_ITfDisplayAttributeProvider.ptr, &pProvider);
+            if (hr is OS.S_OK) {
+                void* pEnum;
+                /* pProvider.EnumDisplayAttributeInfo () */
+                hr = OS.VtblCall (3, pProvider, cast(int)&pEnum);
+                if (hr is OS.S_OK) {
+                    void* pDispInfo;
+                    TF_DISPLAYATTRIBUTE* tempPda;
+                    /* pEnum.Next () */
+                    while ((hr = OS.VtblCall (4, pEnum, 1, cast(int) &pDispInfo, 0 )) is OS.S_OK) {
+                        /* pDispInfo.GetAttributeInfo(); */
+                        OS.VtblCall (5, pDispInfo, cast(int)&tempPda);
+                        /* pDispInfo.Release () */
+                        OS.VtblCall (2, pDispInfo);
+                        if (tempPda.bAttr is attInfo) {
+                            pda = tempPda;
+                            break;
+                        }
+                    }
+                    /* pEnum.Release () */
+                    hr = OS.VtblCall (2, pEnum);
+                }
+                /* pProvider.Release () */
+                hr = OS.VtblCall (2, pProvider);
+            }
+        }
+        /* pProfiles.Release () */
+        hr = OS.VtblCall (2, pProfiles);
+    }
+    if (pda is null) {
+        pda = new TF_DISPLAYATTRIBUTE ();
+        switch (attInfo) {
+            case OS.TF_ATTR_INPUT:
+                pda.lsStyle = OS.TF_LS_SQUIGGLE;
+                break;
+            case OS.TF_ATTR_CONVERTED:
+            case OS.TF_ATTR_TARGET_CONVERTED:
+                pda.lsStyle = OS.TF_LS_SOLID;
+                pda.fBoldLine = attInfo is OS.TF_ATTR_TARGET_CONVERTED;
+                break;
+        }
+    }
+    return pda;
+}
+
+public int [] getRanges () {
+    checkWidget ();
+    if (ranges is null) return new int [0];
+    int [] result = new int [ranges.length];
+    for (int i = 0; i < result.length; i++) {
+        result [i] = ranges [i] + startOffset;
+    }
+    return result;
+}
+
+public TextStyle [] getStyles () {
+    checkWidget ();
+    if (styles is null) return new TextStyle [0];
+    TextStyle [] result = new TextStyle [styles.length];
+    System.arraycopy (styles, 0, result, 0, styles.length);
+    return result;
+}
+
+public String getText () {
+    checkWidget ();
+    return text;
+}
+
+public bool getWideCaret() {
+    checkWidget ();
+    auto layout = OS.GetKeyboardLayout (0);
+    short langID = cast(short)OS.LOWORD ( cast(int) layout);
+    return OS.PRIMARYLANGID (langID) is OS.LANG_KOREAN;
+}
+
+bool isInlineEnabled () {
+    if (OS.IsWinCE || OS.WIN32_VERSION < OS.VERSION (5, 1)) return false;
+    return OS.IsDBLocale && hooks (DWT.ImeComposition);
+}
+
+void releaseParent () {
+    super.releaseParent ();
+    if (this is parent.getIME ()) parent.setIME (null);
+}
+
+void releaseWidget () {
+    super.releaseWidget ();
+    parent = null;
+    text = null;
+    styles = null;
+    ranges = null;
+}
+
+public void setCompositionOffset (int offset) {
+    checkWidget ();
+    if (offset < 0) return;
+    if (startOffset !is -1) {
+        startOffset = offset;
+    }
+}
+
+LRESULT WM_IME_COMPOSITION (int /*long*/ wParam, int /*long*/ lParam) {
+    if (!isInlineEnabled ()) return null;
+    ranges = null;
+    styles = null;
+    caretOffset = commitCount = 0;
+    auto hwnd = parent.handle;
+    auto hIMC = OS.ImmGetContext (hwnd);
+    int codePage = parent.getCodePage ();
+    if (hIMC !is null) {
+        TCHAR[] buffer = null;
+        if ((lParam & OS.GCS_RESULTSTR) !is 0) {
+            int length_ = OS.ImmGetCompositionString (hIMC, OS.GCS_RESULTSTR, null, 0);
+            if (length_ > 0) {
+                buffer = NewTCHARs (codePage, length_ / TCHAR.sizeof);
+                OS.ImmGetCompositionString (hIMC, OS.GCS_RESULTSTR, buffer.ptr, length_);
+                if (startOffset is -1) {
+                    Event event = new Event ();
+                    event.detail = DWT.COMPOSITION_SELECTION;
+                    sendEvent (DWT.ImeComposition, event);
+                    startOffset = event.start;
+                }
+                Event event = new Event ();
+                event.detail = DWT.COMPOSITION_CHANGED;
+                event.start = startOffset;
+                event.end = startOffset + text.length;
+                event.text = text = buffer !is null ? TCHARsToStr(buffer) : "";
+                commitCount = text.length ;
+                sendEvent (DWT.ImeComposition, event);
+                String chars = text;
+                text = "";
+                startOffset = -1;
+                commitCount = 0;
+                if (event.doit) {
+                    Display display = this.display;
+                    display.lastKey = 0;
+                    display.lastVirtual = display.lastNull = display.lastDead = false;
+                    length_ = chars.length;
+                    for (int i = 0; i < length_; i++) {
+                        char c = chars.charAt (i);
+                        display.lastAscii = c;
+                        event = new Event ();
+                        event.character = c;
+                        parent.sendEvent (DWT.KeyDown, event);
+                    }
+                }
+            }
+            if ((lParam & OS.GCS_COMPSTR) is 0) return LRESULT.ONE;
+        }
+        buffer = null;
+        if ((lParam & OS.GCS_COMPSTR) !is 0) {
+            int length_ = OS.ImmGetCompositionString (hIMC, OS.GCS_COMPSTR, null, 0);
+            if (length_ > 0) {
+                buffer = NewTCHARs (codePage, length_ / TCHAR.sizeof);
+                OS.ImmGetCompositionString (hIMC, OS.GCS_COMPSTR, buffer.ptr, length_);
+                if ((lParam & OS.GCS_CURSORPOS) !is 0) {
+                    caretOffset = OS.ImmGetCompositionString (hIMC, OS.GCS_CURSORPOS, null, 0);
+                }
+                int [] clauses = null;
+                if ((lParam & OS.GCS_COMPCLAUSE) !is 0) {
+                    length_ = OS.ImmGetCompositionStringW (hIMC, OS.GCS_COMPCLAUSE, /+cast(int [])+/null, 0);
+                    if (length_ > 0) {
+                        clauses = new int [length_ / 4];
+                        OS.ImmGetCompositionStringW (hIMC, OS.GCS_COMPCLAUSE, clauses.ptr, length_);
+                    }
+                }
+                if ((lParam & OS.GCS_COMPATTR) !is 0 && clauses !is null) {
+                    length_ = OS.ImmGetCompositionStringA (hIMC, OS.GCS_COMPATTR, /+cast(byte [])+/null, 0);
+                    if (length_ > 0) {
+                        byte [] attrs = new byte [length_];
+                        OS.ImmGetCompositionStringA (hIMC, OS.GCS_COMPATTR, attrs.ptr, length_);
+                        length_ = clauses.length - 1;
+                        ranges = new int [length_ * 2];
+                        styles = new TextStyle [length_];
+                        auto layout = OS.GetKeyboardLayout (0);
+                        short langID = cast(short)OS.LOWORD ( cast(int) layout);
+                        TF_DISPLAYATTRIBUTE* attr = null;
+                        TextStyle style = null;
+                        for (int i = 0; i < length_; i++) {
+                            ranges [i * 2] = clauses [i];
+                            ranges [i * 2 + 1] = clauses [i + 1] - 1;
+                            styles [i] = style = new TextStyle ();
+                            attr = getDisplayAttribute (langID, attrs [clauses [i]]);
+                            if (attr !is null) {
+                                switch (attr.crText.type) {
+                                    case OS.TF_CT_COLORREF:
+                                        style.foreground = Color.win32_new (display, attr.crText.cr);
+                                        break;
+                                    case OS.TF_CT_SYSCOLOR:
+                                        int colorRef = OS.GetSysColor (attr.crText.cr);
+                                        style.foreground = Color.win32_new (display, colorRef);
+                                        break;
+                                }
+                                switch (attr.crBk.type) {
+                                    case OS.TF_CT_COLORREF:
+                                        style.background = Color.win32_new (display, attr.crBk.cr);
+                                        break;
+                                    case OS.TF_CT_SYSCOLOR:
+                                        int colorRef = OS.GetSysColor (attr.crBk.cr);
+                                        style.background = Color.win32_new (display, colorRef);
+                                        break;
+                                }
+                                switch (attr.crLine.type) {
+                                    case OS.TF_CT_COLORREF:
+                                        style.underlineColor = Color.win32_new (display, attr.crLine.cr);
+                                        break;
+                                    case OS.TF_CT_SYSCOLOR:
+                                        int colorRef = OS.GetSysColor (attr.crLine.cr);
+                                        style.underlineColor = Color.win32_new (display, colorRef);
+                                        break;
+                                }
+                                style.underline = attr.lsStyle !is OS.TF_LS_NONE;
+                                switch (attr.lsStyle) {
+                                    case OS.TF_LS_SQUIGGLE:
+                                        style.underlineStyle = DWT.UNDERLINE_SQUIGGLE;
+                                        break;
+                                    case OS.TF_LS_DASH:
+                                        style.underlineStyle = UNDERLINE_IME_DASH;
+                                        break;
+                                    case OS.TF_LS_DOT:
+                                        style.underlineStyle = UNDERLINE_IME_DOT;
+                                        break;
+                                    case OS.TF_LS_SOLID:
+                                        style.underlineStyle = attr.fBoldLine ? UNDERLINE_IME_THICK : DWT.UNDERLINE_SINGLE;
+                                        break;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            OS.ImmReleaseContext (hwnd, hIMC);
+        }
+        int end = startOffset + text.length;
+        if (startOffset is -1) {
+            Event event = new Event ();
+            event.detail = DWT.COMPOSITION_SELECTION;
+            sendEvent (DWT.ImeComposition, event);
+            startOffset = event.start;
+            end = event.end;
+        }
+        Event event = new Event ();
+        event.detail = DWT.COMPOSITION_CHANGED;
+        event.start = startOffset;
+        event.end = end;
+        event.text = text = buffer !is null ? TCHARsToStr(buffer) : "";
+        sendEvent (DWT.ImeComposition, event);
+        if (text.length is 0) {
+            startOffset = -1;
+            ranges = null;
+            styles = null;
+        }
+    }
+    return LRESULT.ONE;
+}
+
+LRESULT WM_IME_COMPOSITION_START (int /*long*/ wParam, int /*long*/ lParam) {
+    return isInlineEnabled () ? LRESULT.ONE : null;
+}
+
+LRESULT WM_IME_ENDCOMPOSITION (int /*long*/ wParam, int /*long*/ lParam) {
+    return isInlineEnabled () ? LRESULT.ONE : null;
+}
+
+LRESULT WM_KILLFOCUS (int /*long*/ wParam, int /*long*/ lParam) {
+    if (!isInlineEnabled ()) return null;
+    auto hwnd = parent.handle;
+    auto hIMC = OS.ImmGetContext (hwnd);
+    if (hIMC !is null) {
+        if (OS.ImmGetOpenStatus (hIMC)) {
+            OS.ImmNotifyIME (hIMC, OS.NI_COMPOSITIONSTR, OS.CPS_COMPLETE, 0);
+        }
+        OS.ImmReleaseContext (hwnd, hIMC);
+    }
+    return null;
+}
+
+LRESULT WM_LBUTTONDOWN (int /*long*/ wParam, int /*long*/ lParam) {
+    if (!isInlineEnabled ()) return null;
+    auto hwnd = parent.handle;
+    auto hIMC = OS.ImmGetContext (hwnd);
+    if (hIMC !is null) {
+        if (OS.ImmGetOpenStatus (hIMC)) {
+            if (OS.ImmGetCompositionString (hIMC, OS.GCS_COMPSTR, null, 0) > 0) {
+                Event event = new Event ();
+                event.detail = DWT.COMPOSITION_OFFSET;
+                event.x = OS.GET_X_LPARAM (lParam);
+                event.y = OS.GET_Y_LPARAM (lParam);
+                sendEvent (DWT.ImeComposition, event);
+                int offset = event.index;
+                int length_ = text.length;
+                if (offset !is -1 && startOffset !is -1 && startOffset <= offset && offset < startOffset + length_) {
+                    auto imeWnd = OS.ImmGetDefaultIMEWnd (hwnd);
+                    offset = event.index + event.count - startOffset;
+                    int trailing = event.count > 0 ? 1 : 2;
+                    int /*long*/ param = OS.MAKEWPARAM (OS.MAKEWORD (OS.IMEMOUSE_LDOWN, trailing), offset);
+                    OS.SendMessage (imeWnd, WM_MSIME_MOUSE, param, hIMC);
+                } else {
+                    OS.ImmNotifyIME (hIMC, OS.NI_COMPOSITIONSTR, OS.CPS_COMPLETE, 0);
+                }
+            }
+        }
+        OS.ImmReleaseContext (hwnd, hIMC);
+    }
+    return null;
+}
+
+}
--- a/dwt/widgets/Label.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/Label.d	Sat May 17 17:34:28 2008 +0200
@@ -34,6 +34,13 @@
  * user interface object that displays a string or image.
  * When SEPARATOR is specified, displays a single
  * vertical or horizontal line.
+ * <p>
+ * Shadow styles are hints and may not be honoured
+ * by the platform.  To create a separator label
+ * with the default shadow style for the platform,
+ * do not specify a shadow style.
+ * </p>
+ * <dl>
  * <dl>
  * <dt><b>Styles:</b></dt>
  * <dd>SEPARATOR, HORIZONTAL, VERTICAL</dd>
@@ -513,6 +520,7 @@
 
 override LRESULT WM_UPDATEUISTATE (int wParam, int lParam) {
     LRESULT result = super.WM_UPDATEUISTATE (wParam, lParam);
+    if (result !is null) return result;
     /*
     * Feature in Windows.  When WM_UPDATEUISTATE is sent to
     * a static control, it sends WM_CTLCOLORSTATIC to get the
@@ -531,7 +539,7 @@
     }
     if (redraw) {
         OS.InvalidateRect (handle, null, false);
-        int code = OS.DefWindowProc (handle, OS.WM_UPDATEUISTATE, wParam, lParam);
+        int /*long*/ code = OS.DefWindowProc (handle, OS.WM_UPDATEUISTATE, wParam, lParam);
         return new LRESULT (code);
     }
     return result;
--- a/dwt/widgets/Link.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/Link.d	Sat May 17 17:34:28 2008 +0200
@@ -92,6 +92,34 @@
                 WNDCLASS lpWndClass;
                 OS.GetClassInfo (null, LinkClass.ptr, &lpWndClass);
                 LinkProc = lpWndClass.lpfnWndProc;
+            /*
+            * Feature in Windows.  The SysLink window class
+            * does not include CS_DBLCLKS.  This means that these
+            * controls will not get double click messages such as
+            * WM_LBUTTONDBLCLK.  The fix is to register a new
+            * window class with CS_DBLCLKS.
+            *
+            * NOTE:  Screen readers look for the exact class name
+            * of the control in order to provide the correct kind
+            * of assistance.  Therefore, it is critical that the
+            * new window class have the same name.  It is possible
+            * to register a local window class with the same name
+            * as a global class.  Since bits that affect the class
+            * are being changed, it is possible that other native
+            * code, other than DWT, could create a control with
+            * this class name, and fail unexpectedly.
+            */
+            auto hInstance = OS.GetModuleHandle (null);
+            auto hHeap = OS.GetProcessHeap ();
+            lpWndClass.hInstance = hInstance;
+            lpWndClass.style &= ~OS.CS_GLOBALCLASS;
+            lpWndClass.style |= OS.CS_DBLCLKS;
+            int byteCount = LinkClass.length * TCHAR.sizeof;
+            auto lpszClassName = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+            OS.MoveMemory (lpszClassName, LinkClass.ptr, byteCount);
+            lpWndClass.lpszClassName = lpszClassName;
+            OS.RegisterClass (&lpWndClass);
+            OS.HeapFree (hHeap, 0, lpszClassName);
             } else {
                 LinkProc = null;
             }
@@ -165,7 +193,24 @@
 
 override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) {
     if (handle is null) return 0;
-    if (LinkProc !is null) return OS.CallWindowProc (LinkProc, hwnd, msg, wParam, lParam);
+    if (LinkProc !is null) {
+        /*
+        * Feature in Windows.  By convention, native Windows controls
+        * check for a non-NULL wParam, assume that it is an HDC and
+        * paint using that device.  The SysLink control does not.
+        * The fix is to check for an HDC and use WM_PRINTCLIENT.
+        */
+        switch (msg) {
+            case OS.WM_PAINT:
+                if (wParam !is 0) {
+                    OS.SendMessage (hwnd, OS.WM_PRINTCLIENT, wParam, 0);
+                    return 0;
+                }
+                break;
+            default:
+        }
+        return OS.CallWindowProc (LinkProc, hwnd, msg, wParam, lParam);
+    }
     return OS.DefWindowProc (hwnd, msg, wParam, lParam);
 }
 
@@ -178,16 +223,23 @@
         auto hDC = OS.GetDC (handle);
         auto newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
         auto oldFont = OS.SelectObject (hDC, newFont);
-        TCHAR[] buffer = StrToTCHARs (getCodePage (), parse (text));
-        RECT rect;
-        int flags = OS.DT_CALCRECT | OS.DT_NOPREFIX;
-        if (wHint !is DWT.DEFAULT) {
-            flags |= OS.DT_WORDBREAK;
-            rect.right = wHint;
+        if (text.length > 0) {
+            TCHAR[] buffer = StrToTCHARs (getCodePage (), parse (text));
+            RECT rect;
+            int flags = OS.DT_CALCRECT | OS.DT_NOPREFIX;
+            if (wHint !is DWT.DEFAULT) {
+                flags |= OS.DT_WORDBREAK;
+                rect.right = wHint;
+            }
+            OS.DrawText (hDC, buffer.ptr, buffer.length, &rect, flags);
+            width = rect.right - rect.left;
+            height = rect.bottom;
+        } else {
+            TEXTMETRIC lptm;
+            OS.GetTextMetrics (hDC, &lptm);
+            width = 0;
+            height = lptm.tmHeight;
         }
-        OS.DrawText (hDC, buffer.ptr, buffer.length, &rect, flags);
-        width = rect.right - rect.left;
-        height = rect.bottom;
         if (newFont !is null) OS.SelectObject (hDC, oldFont);
         OS.ReleaseDC (handle, hDC);
     } else {
@@ -527,7 +579,7 @@
     }
     if (start < length_) {
         int tmp = parseMnemonics (buffer, start, tagStart, result);
-        int mnemonic = parseMnemonics (buffer, linkStart, index, result);
+        int mnemonic = parseMnemonics (buffer, Math.max (tagStart, linkStart), length_, result);
         if (mnemonic is -1) mnemonic = tmp;
         mnemonics [linkIndex] = mnemonic;
     } else {
@@ -726,7 +778,7 @@
                 * This allows the application to cancel an operation that is normally
                 * performed in WM_KEYDOWN from WM_CHAR.
                 */
-                int code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam);
+                int /*long*/ code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam);
                 return new LRESULT (code);
             default:
         }
@@ -738,7 +790,8 @@
 override LRESULT WM_GETDLGCODE (int wParam, int lParam) {
     LRESULT result = super.WM_GETDLGCODE (wParam, lParam);
     if (result !is null) return result;
-    int index, count, code = 0;
+    int index, count;
+    int /*long*/ code = 0;
     if (OS.COMCTL32_MAJOR >= 6) {
         LITEM item;
         item.mask = OS.LIF_ITEMINDEX | OS.LIF_STATE;
@@ -772,7 +825,7 @@
 override LRESULT WM_GETFONT (int wParam, int lParam) {
     LRESULT result = super.WM_GETFONT (wParam, lParam);
     if (result !is null) return result;
-    int code = callWindowProc (handle, OS.WM_GETFONT, wParam, lParam);
+    int /*long*/ code = callWindowProc (handle, OS.WM_GETFONT, wParam, lParam);
     if (code !is 0) return new LRESULT (code);
     if (font is null) font = defaultFont ();
     return new LRESULT ( cast(int) font);
@@ -810,8 +863,8 @@
     if (result is LRESULT.ZERO) return result;
     if (OS.COMCTL32_MAJOR < 6) {
         if (focusIndex !is -1) setFocus ();
-        int x = lParam & 0xFFFF;
-        int y = lParam >> 16;
+        int x = OS.GET_X_LPARAM (lParam);
+        int y = OS.GET_Y_LPARAM (lParam);
         int offset = layout.getOffset (x, y, null);
         int oldSelectionX = selection.x;
         int oldSelectionY = selection.y;
@@ -848,8 +901,8 @@
     if (result is LRESULT.ZERO) return result;
     if (OS.COMCTL32_MAJOR < 6) {
         if (mouseDownIndex is -1) return result;
-        int x = lParam & 0xFFFF;
-        int y = lParam >> 16;
+        int x = OS.GET_X_LPARAM (lParam);
+        int y = OS.GET_Y_LPARAM (lParam);
         Rectangle [] rects = getRectangles (mouseDownIndex);
         for (int i = 0; i < rects.length; i++) {
             Rectangle rect = rects [i];
@@ -865,11 +918,25 @@
     return result;
 }
 
+override LRESULT WM_NCHITTEST (int wParam, int lParam) {
+    LRESULT result = super.WM_NCHITTEST (wParam, lParam);
+    if (result !is null) return result;
+
+    /*
+    * Feature in Windows. For WM_NCHITTEST, the Syslink window proc
+    * returns HTTRANSPARENT when mouse is over plain text. The fix is
+    * to always return HTCLIENT.
+    */
+    if (OS.COMCTL32_MAJOR >= 6) return new LRESULT (OS.HTCLIENT);
+
+    return result;
+}
+
 override LRESULT WM_MOUSEMOVE (int wParam, int lParam) {
     LRESULT result = super.WM_MOUSEMOVE (wParam, lParam);
     if (OS.COMCTL32_MAJOR < 6) {
-        int x = lParam & 0xFFFF;
-        int y = lParam >> 16;
+        int x = OS.GET_X_LPARAM (lParam);
+        int y = OS.GET_Y_LPARAM (lParam);
         if (OS.GetKeyState (OS.VK_LBUTTON) < 0) {
             int oldSelection = selection.y;
             selection.y = layout.getOffset (x, y, null);
--- a/dwt/widgets/List.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/List.d	Sat May 17 17:34:28 2008 +0200
@@ -202,7 +202,27 @@
 
 override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) {
     if (handle is null) return 0;
-    return OS.CallWindowProc (ListProc, hwnd, msg, wParam, lParam);
+    bool redraw = false;
+    switch (msg) {
+        case OS.WM_HSCROLL:
+        case OS.WM_VSCROLL: {
+            redraw = findImageControl () !is null && drawCount is 0 && OS.IsWindowVisible (handle);
+            if (redraw) OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+            break;
+        }
+    }
+    int /*long*/ code = OS.CallWindowProc (ListProc, hwnd, msg, wParam, lParam);
+    switch (msg) {
+        case OS.WM_HSCROLL:
+        case OS.WM_VSCROLL: {
+            if (redraw) {
+                OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+                OS.InvalidateRect (handle, null, true);
+            }
+            break;
+        }
+    }
+    return code;
 }
 
 static int checkStyle (int style) {
@@ -1203,8 +1223,8 @@
     for (int i=0; i<items.length; i++) {
         if (items [i] is null) error (DWT.ERROR_INVALID_ARGUMENT);
     }
-    int oldProc = OS.GetWindowLong (handle, OS.GWL_WNDPROC);
-    OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) ListProc);
+    int /*long*/ oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC);
+    OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR) ListProc);
     bool redraw = drawCount is 0 && OS.IsWindowVisible (handle);
     if (redraw) {
         OS.SendMessage (handle, OS.WM_SETREDRAW, 0, 0);
@@ -1255,7 +1275,7 @@
 //      int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE;
 //      OS.RedrawWindow (handle, null, 0, flags);
     }
-    OS.SetWindowLong (handle, OS.GWL_WNDPROC, oldProc);
+    OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc);
     if (index < items.length) error (DWT.ERROR_ITEM_NOT_ADDED);
 }
 
@@ -1532,7 +1552,146 @@
     return cast(int) ListProc;
 }
 
-override LRESULT WM_SIZE (int wParam, int lParam) {
+override LRESULT WM_CHAR (int wParam, int lParam) {
+    LRESULT result = super.WM_CHAR (wParam, lParam);
+    if (result !is null) return result;
+    /*
+    * Feature in Windows.  The Windows list box does not implement
+    * the control key interface for multi-select list boxes, making
+    * it inaccessible from the keyboard.  The fix is to implement
+    * the key processing.
+    */
+    if (OS.GetKeyState (OS.VK_CONTROL) < 0 && OS.GetKeyState (OS.VK_SHIFT) >= 0) {
+        int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+        if ((bits & OS.LBS_EXTENDEDSEL) !is 0) {
+            switch (wParam) {
+                case OS.VK_SPACE: {
+                    int index = OS.SendMessage (handle, OS.LB_GETCARETINDEX, 0, 0);
+                    int code = OS.SendMessage (handle, OS.LB_GETSEL, index, 0);
+                    if (code is OS.LB_ERR) break;
+                    OS.SendMessage (handle, OS.LB_SETSEL, code !is 0 ? 0 : 1, index);
+                    OS.SendMessage (handle, OS.LB_SETANCHORINDEX, index, 0);
+                    postEvent (DWT.Selection);
+                    return LRESULT.ZERO;
+                }
+            }
+        }
+    }
+    return result;
+}
+
+override LRESULT WM_KEYDOWN (int /*long*/ wParam, int /*long*/ lParam) {
+    LRESULT result = super.WM_KEYDOWN (wParam, lParam);
+    if (result !is null) return result;
+    /*
+    * Feature in Windows.  The Windows list box does not implement
+    * the control key interface for multi-select list boxes, making
+    * it inaccessible from the keyboard.  The fix is to implement
+    * the key processing.
+    */
+    if (OS.GetKeyState (OS.VK_CONTROL) < 0 && OS.GetKeyState (OS.VK_SHIFT) >= 0) {
+        int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+        if ((bits & OS.LBS_EXTENDEDSEL) !is 0) {
+            int location = -1;
+            switch (wParam) {
+                case OS.VK_SPACE: {
+                    /*
+                    * Ensure that the window proc does not process VK_SPACE
+                    * so that it can be handled in WM_CHAR.  This allows the
+                    * application to cancel an operation that is normally
+                    * performed in WM_KEYDOWN from WM_CHAR.
+                    */
+                    return LRESULT.ZERO;
+                }
+                case OS.VK_UP:
+                case OS.VK_DOWN: {
+                    int index = OS.SendMessage (handle, OS.LB_GETCARETINDEX, 0, 0);
+                    location = Math.max (0, index + ((wParam) is OS.VK_UP ? -1 : 1));
+                    break;
+                }
+                case OS.VK_PRIOR: {
+                    int index = OS.SendMessage (handle, OS.LB_GETCARETINDEX, 0, 0);
+                    int topIndex = OS.SendMessage (handle, OS.LB_GETTOPINDEX, 0, 0);
+                    if (index !is topIndex) {
+                        location = topIndex;
+                    } else {
+                        forceResize ();
+                        RECT rect;
+                        OS.GetClientRect (handle, &rect);
+                        int itemHeight = OS.SendMessage (handle, OS.LB_GETITEMHEIGHT, 0, 0);
+                        int pageSize = Math.max (2, (rect.bottom / itemHeight));
+                        location = Math.max (0, topIndex - (pageSize - 1));
+                    }
+                    break;
+                }
+                case OS.VK_NEXT: {
+                    int index = OS.SendMessage (handle, OS.LB_GETCARETINDEX, 0, 0);
+                    int topIndex = OS.SendMessage (handle, OS.LB_GETTOPINDEX, 0, 0);
+                    forceResize ();
+                    RECT rect;
+                    OS.GetClientRect (handle, &rect);
+                    int itemHeight = OS.SendMessage (handle, OS.LB_GETITEMHEIGHT, 0, 0);
+                    int pageSize = Math.max (2, (rect.bottom / itemHeight));
+                    int bottomIndex = topIndex + pageSize - 1;
+                    if (index !is bottomIndex) {
+                        location = bottomIndex;
+                    } else {
+                        location = bottomIndex + pageSize - 1;
+                    }
+                    int count = OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
+                    if (count !is OS.LB_ERR) location = Math.min (count - 1, location);
+                    break;
+                }
+                case OS.VK_HOME: {
+                    location = 0;
+                    break;
+                }
+                case OS.VK_END: {
+                    int count = OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0);
+                    if (count is OS.LB_ERR) break;
+                    location = count - 1;
+                    break;
+                }
+            }
+            if (location !is -1) {
+                OS.SendMessage (handle, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0);
+                OS.SendMessage (handle, OS.LB_SETCARETINDEX, location, 0);
+                return LRESULT.ZERO;
+            }
+        }
+    }
+
+    /*
+    * Feature in Windows.  When the user changes focus using
+    * the keyboard, the focus indicator does not draw.  The
+    * fix is to update the UI state for the control whenever
+    * the focus indicator changes as a result of something
+    * the user types.
+    */
+    int uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
+    if ((uiState & OS.UISF_HIDEFOCUS) !is 0) {
+        int oldIndex = OS.SendMessage (handle, OS.LB_GETCARETINDEX, 0, 0);
+        int /*long*/ code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam);
+        int newIndex = OS.SendMessage (handle, OS.LB_GETCARETINDEX, 0, 0);
+        if (oldIndex !is newIndex) {
+            OS.SendMessage (handle, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0);
+            /*
+            * Bug in Windows.  When the WM_CHANGEUISTATE is used
+            * to update the UI state for a list that has been
+            * selected using Shift+Arrow, the focus indicator
+            * has pixel corruption.  The fix is to redraw the
+            * focus item.
+            */
+            RECT itemRect;
+            OS.SendMessage (handle, OS.LB_GETITEMRECT, newIndex, &itemRect);
+            OS.InvalidateRect (handle, &itemRect, true);
+        }
+        return new LRESULT (code);
+    }
+    return result;
+}
+
+override LRESULT WM_SIZE (int /*long*/ wParam, int /*long*/ lParam) {
     /*
     * Bug in Windows.  If the top index is changed while the
     * list is being resized, Windows does not redraw properly
@@ -1561,7 +1720,7 @@
 }
 
 override LRESULT wmCommandChild (int wParam, int lParam) {
-    int code = wParam >> 16;
+    int code = OS.HIWORD (wParam);
     switch (code) {
         case OS.LBN_SELCHANGE:
             postEvent (DWT.Selection);
--- a/dwt/widgets/Menu.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/Menu.d	Sat May 17 17:34:28 2008 +0200
@@ -89,6 +89,11 @@
  * Constructs a new instance of this class given its parent,
  * and sets the style for the instance so that the instance
  * will be a popup menu on the given parent's shell.
+ * <p>
+ * After constructing a menu, it can be set into its parent
+ * using <code>parent.setMenu(menu)</code>.  In this case, the parent may
+ * be any control in the same widget tree as the parent.
+ * </p>
  *
  * @param parent a control which will be the parent of the new instance (cannot be null)
  *
@@ -120,6 +125,9 @@
  * of those <code>DWT</code> style constants. The class description
  * lists the style constants that are applicable to the class.
  * Style bits are also inherited from superclasses.
+ * </p><p>
+ * After constructing a menu or menuBar, it can be set into its parent
+ * using <code>parent.setMenu(menu)</code> or <code>parent.setMenuBar(menuBar)</code>.
  * </p>
  *
  * @param parent a decorations control which will be the parent of the new instance (cannot be null)
@@ -148,6 +156,10 @@
  * (which must be a <code>Menu</code>) and sets the style
  * for the instance so that the instance will be a drop-down
  * menu on the given parent's parent.
+ * <p>
+ * After constructing a drop-down menu, it can be set into its parentMenu
+ * using <code>parentMenu.setMenu(menu)</code>.
+ * </p>
  *
  * @param parentMenu a menu which will be the parent of the new instance (cannot be null)
  *
@@ -172,6 +184,10 @@
  * (which must be a <code>MenuItem</code>) and sets the style
  * for the instance so that the instance will be a drop-down
  * menu on the given parent's parent menu.
+ * <p>
+ * After constructing a drop-down menu, it can be set into its parentItem
+ * using <code>parentItem.setMenu(menu)</code>.
+ * </p>
  *
  * @param parentItem a menu item which will be the parent of the new instance (cannot be null)
  *
@@ -227,8 +243,8 @@
         int nX = x, nY = y;
         if (!hasLocation) {
             int pos = OS.GetMessagePos ();
-            nX = cast(short) (pos & 0xFFFF);
-            nY = cast(short) (pos >> 16);
+            nX = OS.GET_X_LPARAM (pos);
+            nY = OS.GET_Y_LPARAM (pos);
         }
         /*
         * Feature in Windows.  It is legal use TrackPopupMenu()
@@ -238,14 +254,14 @@
         * that the menu has been closed.  This is not strictly a
         * bug but leads to unwanted behavior when application code
         * assumes that every WM_INITPOPUPMENU will eventually result
-        * in a WM_MENUSELECT, wParam=0xFFFF0000, lParam=0 to indicate
-        * that the menu has been closed.  The fix is to detect the
-        * case when TrackPopupMenu() fails and the number of items in
+        * in a WM_MENUSELECT, wParam=MAKEWPARAM (0, 0xFFFF), lParam=0 to
+        * indicate that the menu has been closed.  The fix is to detect
+        * the case when TrackPopupMenu() fails and the number of items in
         * the menu is zero and issue a fake WM_MENUSELECT.
         */
         bool success = cast(bool) OS.TrackPopupMenu (handle, flags, nX, nY, 0, hwndParent, null);
         if (!success && GetMenuItemCount (handle) is 0) {
-            OS.SendMessage (hwndParent, OS.WM_MENUSELECT, 0xFFFF0000, 0);
+            OS.SendMessage (hwndParent, OS.WM_MENUSELECT, OS.MAKEWPARAM (0, 0xFFFF), 0);
         }
     } else {
         OS.SendMessage (hwndParent, OS.WM_CANCELMODE, 0, 0);
@@ -385,7 +401,7 @@
 
             /* Set first item */
             if (nToolBarId is ID_SPMM || nToolBarId is ID_SPMB) {
-                int hMenu = OS.SendMessage (hwndCB, OS.SHCMBM_GETSUBMENU, 0, ID_SPSOFTKEY0);
+                int /*long*/ hMenu = OS.SendMessage (hwndCB, OS.SHCMBM_GETSUBMENU, 0, ID_SPSOFTKEY0);
                 /* Remove the item from the resource file */
                 OS.RemoveMenu (hMenu, 0, OS.MF_BYPOSITION);
                 Menu menu = new Menu (parent, DWT.DROP_DOWN, hMenu);
@@ -398,7 +414,7 @@
 
             /* Set second item */
             if (nToolBarId is ID_SPMM || nToolBarId is ID_SPBM) {
-                int hMenu = OS.SendMessage (hwndCB, OS.SHCMBM_GETSUBMENU, 0, ID_SPSOFTKEY1);
+                int /*long*/ hMenu = OS.SendMessage (hwndCB, OS.SHCMBM_GETSUBMENU, 0, ID_SPSOFTKEY1);
                 OS.RemoveMenu (hMenu, 0, OS.MF_BYPOSITION);
                 Menu menu = new Menu (parent, DWT.DROP_DOWN, hMenu);
                 item = new MenuItem (this, menu, DWT.CASCADE, 1);
@@ -414,7 +430,7 @@
             * a result, Shell on WinCE SP must use the class Dialog.
             */
             int dwMask = OS.SHMBOF_NODEFAULT | OS.SHMBOF_NOTIFY;
-            int lParam = dwMask << 16 | dwMask;
+            int /*long*/ lParam = OS.MAKELPARAM (dwMask, dwMask);
             OS.SendMessage (hwndCB, OS.SHCMBM_OVERRIDEKEY, OS.VK_ESCAPE, lParam);
             return;
         }
@@ -493,7 +509,8 @@
             MENUITEMINFO info;
             info.cbSize = MENUITEMINFO.sizeof;
             info.fMask = OS.MIIM_ID | OS.MIIM_TYPE | OS.MIIM_DATA;
-            info.wID = info.dwItemData = item.id;
+            info.wID = item.id;
+            info.dwItemData = item.id;
             info.fType = item.widgetStyle ();
             info.dwTypeData = pszText;
             success = cast(bool) OS.InsertMenuItem (handle, index, true, &info);
@@ -583,6 +600,7 @@
 }
 
 override void destroyWidget () {
+    MenuItem cascade = this.cascade;
     HMENU hMenu = handle;
     HWND hCB = hwndCB;
     releaseHandle ();
@@ -591,7 +609,11 @@
             OS.CommandBar_Destroy (hCB);
         }
     } else {
-        if (hMenu !is null) OS.DestroyMenu (hMenu);
+        if (cascade !is null) {
+            if (!OS.IsSP) cascade.setMenu (null, true);
+        } else {
+            if (hMenu !is null) OS.DestroyMenu (hMenu);
+        }
     }
 }
 
@@ -1116,7 +1138,7 @@
 override void releaseHandle () {
     super.releaseHandle ();
     handle = null;
-    hwndCB = null;
+    cascade = null;
 }
 
 override void releaseChildren (bool destroy) {
@@ -1136,7 +1158,6 @@
 
 override void releaseParent () {
     super.releaseParent ();
-    if (cascade !is null) cascade.releaseMenu ();
     if ((style & DWT.BAR) !is 0) {
         display.removeBar (this);
         if (this is parent.menuBar) {
@@ -1163,7 +1184,6 @@
     }
     if (parent !is null) parent.removeMenu (this);
     parent = null;
-    cascade = null;
 }
 
 /**
--- a/dwt/widgets/MenuItem.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/MenuItem.d	Sat May 17 17:34:28 2008 +0200
@@ -279,10 +279,10 @@
     releaseHandle ();
 }
 
-void fillAccel (ACCEL* accel) {
-    accel.fVirt = 0;
-    accel.cmd = accel.key = 0;
-    if (accelerator is 0 || !getEnabled ()) return;
+bool fillAccel (ACCEL* accel) {
+    accel.cmd = accel.key = accel.fVirt = 0;
+    if (accelerator is 0 || !getEnabled ()) return false;
+    if ((accelerator & DWT.COMMAND) !is 0) return false;
     int fVirt = OS.FVIRTKEY;
     int key = accelerator & DWT.KEY_MASK;
     auto vKey = Display.untranslateKey (key);
@@ -300,7 +300,7 @@
             case 127: key = OS.VK_DELETE; break;
             default: {
                 key = Display.wcsToMbcs (cast(char) key);
-                if (key is 0) return;
+                if (key is 0) return false;
                 static if (OS.IsWinCE) {
                     key = cast(int) OS.CharUpper (cast(TCHAR*) key);
                 } else {
@@ -320,6 +320,7 @@
     if ((accelerator & DWT.ALT) !is 0) accel.fVirt |= OS.FALT;
     if ((accelerator & DWT.SHIFT) !is 0) accel.fVirt |= OS.FSHIFT;
     if ((accelerator & DWT.CONTROL) !is 0) accel.fVirt |= OS.FCONTROL;
+    return true;
 }
 
 void fixMenus (Decorations newParent) {
@@ -428,6 +429,15 @@
         OS.SendMessage (hwndCB, OS.TB_GETBUTTONINFO, id, &info);
         return (info.fsState & OS.TBSTATE_ENABLED) !is 0;
     }
+    /*
+    * Feature in Windows.  For some reason, when the menu item
+    * is a separator, GetMenuItemInfo() always indicates that
+    * the item is not enabled.  The fix is to track the enabled
+    * state for separators.
+    */
+    if ((style & DWT.SEPARATOR) !is 0) {
+        return (state & DISABLED) is 0;
+    }
     auto hMenu = parent.handle;
     MENUITEMINFO info;
     info.cbSize = MENUITEMINFO.sizeof;
@@ -543,11 +553,6 @@
     id = -1;
 }
 
-void releaseMenu () {
-    if (!OS.IsSP) setMenu (null);
-    menu = null;
-}
-
 override void releaseParent () {
     super.releaseParent ();
     if (menu !is null) menu.dispose ();
@@ -695,6 +700,19 @@
         if (enabled) info.fsState |= OS.TBSTATE_ENABLED;
         OS.SendMessage (hwndCB, OS.TB_SETBUTTONINFO, id, &info);
     } else {
+        /*
+        * Feature in Windows.  For some reason, when the menu item
+        * is a separator, GetMenuItemInfo() always indicates that
+        * the item is not enabled.  The fix is to track the enabled
+        * state for separators.
+        */
+        if ((style & DWT.SEPARATOR) !is 0) {
+            if (enabled) {
+                state &= ~DISABLED;
+            } else {
+                state |= DISABLED;
+            }
+        }
         auto hMenu = parent.handle;
         static if (OS.IsWinCE) {
             int index = parent.indexOf (this);
@@ -756,7 +774,7 @@
     super.setImage (image);
     static if (OS.IsWinCE) {
         if ((OS.IsPPC || OS.IsSP) && parent.hwndCB !is null) {
-            int hwndCB = parent.hwndCB;
+            int /*long*/ hwndCB = parent.hwndCB;
             TBBUTTONINFO info;
             info.cbSize = TBBUTTONINFO.sizeof;
             info.dwMask = OS.TBIF_IMAGE;
@@ -825,6 +843,10 @@
             error (DWT.ERROR_INVALID_PARENT);
         }
     }
+    setMenu (menu, false);
+}
+
+void setMenu (Menu menu, bool dispose) {
 
     /* Assign the new menu */
     Menu oldMenu = this.menu;
@@ -841,14 +863,6 @@
         }
         if (OS.IsSP) error (DWT.ERROR_CANNOT_SET_MENU);
     } else {
-        /*
-        * Feature in Windows.  When SetMenuItemInfo () is used to
-        * set a submenu and the menu item already has a submenu,
-        * Windows destroys the previous menu.  This is undocumented
-        * and unexpected but not necessarily wrong.  The fix is to
-        * remove the item with RemoveMenu () which does not destroy
-        * the submenu and then insert the item with InsertMenuItem ().
-        */
         HMENU hMenu = parent.handle;
         MENUITEMINFO info;
         info.cbSize = MENUITEMINFO.sizeof;
@@ -859,41 +873,33 @@
             index++;
         }
         if (info.dwItemData !is id) return;
-        bool restoreBitmap = false, success = false;
-
+        int cch = 128;
+        auto hHeap = OS.GetProcessHeap ();
+        int byteCount = cch * TCHAR.sizeof;
+        auto pszText = cast(TCHAR*)OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+        info.fMask = OS.MIIM_STATE | OS.MIIM_ID | OS.MIIM_DATA;
         /*
         * Bug in Windows.  When GetMenuItemInfo() is used to get the text,
         * for an item that has a bitmap set using MIIM_BITMAP, the text is
         * not returned.  This means that when SetMenuItemInfo() is used to
         * set the submenu and the current menu state, the text is lost.
-        * The fix is to temporarily remove the bitmap and restore it after
-        * the text and submenu have been set.
+        * The fix is use MIIM_BITMAP and MIIM_STRING.
         */
         if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (4, 10)) {
-            info.fMask = OS.MIIM_BITMAP;
-            OS.GetMenuItemInfo (hMenu, index, true, &info);
-            restoreBitmap = info.hbmpItem !is null || parent.foreground !is -1;
-            if (restoreBitmap) {
-                info.hbmpItem = null;
-                success = cast(bool) OS.SetMenuItemInfo (hMenu, id, false, &info);
-            }
+            info.fMask |= OS.MIIM_BITMAP | OS.MIIM_STRING;
+        } else {
+            info.fMask |= OS.MIIM_TYPE;
         }
-
-        int cch = 128;
-        auto hHeap = OS.GetProcessHeap ();
-        int byteCount = cch * TCHAR.sizeof;
-        auto pszText = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
-        info.fMask = OS.MIIM_STATE | OS.MIIM_ID | OS.MIIM_TYPE | OS.MIIM_DATA;
         info.dwTypeData = pszText;
         info.cch = cch;
-        success = cast(bool) OS.GetMenuItemInfo (hMenu, index, true, &info);
+        bool success = cast(bool) OS.GetMenuItemInfo (hMenu, index, true, &info);
         if (menu !is null) {
             menu.cascade = this;
             info.fMask |= OS.MIIM_SUBMENU;
             info.hSubMenu = menu.handle;
         }
-        OS.RemoveMenu (hMenu, index, OS.MF_BYPOSITION);
-        static if (OS.IsWinCE) {
+        if (OS.IsWinCE) {
+            OS.RemoveMenu (hMenu, index, OS.MF_BYPOSITION);
             /*
             * On WinCE, InsertMenuItem() is not available.  The fix is to
             * use SetMenuItemInfo() but this call does not set the menu item
@@ -901,17 +907,17 @@
             * the item, SetMenuItemInfo() to set the string and EnableMenuItem()
             * and CheckMenuItem() to set the state.
             */
-            int uIDNewItem = id;
+            int /*long*/ uIDNewItem = id;
             int uFlags = OS.MF_BYPOSITION;
             if (menu !is null) {
                 uFlags |= OS.MF_POPUP;
-                uIDNewItem = menu.handle;
+                uIDNewItem = cast(int)menu.handle;
             }
-            TCHAR lpNewItem = new TCHAR (0, " ", true);
-            success = OS.InsertMenu (hMenu, index, uFlags, uIDNewItem, lpNewItem);
+            TCHAR[] lpNewItem = StrToTCHARs (0, " ", true);
+            success = OS.InsertMenu (hMenu, index, uFlags, uIDNewItem, lpNewItem.ptr) !is 0;
             if (success) {
                 info.fMask = OS.MIIM_DATA | OS.MIIM_TYPE;
-                success = OS.SetMenuItemInfo (hMenu, index, true, info);
+                success = OS.SetMenuItemInfo (hMenu, index, true, &info) !is 0;
                 if ((info.fState & (OS.MFS_DISABLED | OS.MFS_GRAYED)) !is 0) {
                     OS.EnableMenuItem (hMenu, index, OS.MF_BYPOSITION | OS.MF_GRAYED);
                 }
@@ -920,26 +926,19 @@
                 }
             }
         } else {
-            success = cast(bool) OS.InsertMenuItem (hMenu, index, true, &info);
-            /*
-            * Restore the bitmap that was removed to work around a problem
-            * in GetMenuItemInfo() and menu items that have bitmaps set with
-            * MIIM_BITMAP.
-            */
-            if (OS.WIN32_VERSION >= OS.VERSION (4, 10)) {
-                if (restoreBitmap) {
-                    info.fMask = OS.MIIM_BITMAP;
-                    if (parent.foreground !is -1) {
-                        info.hbmpItem = OS.HBMMENU_CALLBACK;
-                    } else {
-                        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
-                            info.hbmpItem = hBitmap;
-                        } else {
-                            info.hbmpItem = OS.HBMMENU_CALLBACK;
-                        }
-                    }
-                    success = cast(bool) OS.SetMenuItemInfo (hMenu, id, false, &info);
-                }
+            if (dispose || oldMenu is null) {
+                success = cast(bool) OS.SetMenuItemInfo (hMenu, index, true, &info);
+            } else {
+                /*
+                * Feature in Windows.  When SetMenuItemInfo () is used to
+                * set a submenu and the menu item already has a submenu,
+                * Windows destroys the previous menu.  This is undocumented
+                * and unexpected but not necessarily wrong.  The fix is to
+                * remove the item with RemoveMenu () which does not destroy
+                * the submenu and then insert the item with InsertMenuItem ().
+                */
+                OS.RemoveMenu (hMenu, index, OS.MF_BYPOSITION);
+                success = OS.InsertMenuItem (hMenu, index, true, &info) !is 0;
             }
         }
         if (pszText !is null ) OS.HeapFree (hHeap, 0, pszText);
@@ -1085,49 +1084,24 @@
         info.cbSize = MENUITEMINFO.sizeof;
         auto hMenu = parent.handle;
 
-        /*
-        * Bug in Windows 2000.  For some reason, when MIIM_TYPE is set
-        * on a menu item that also has MIIM_BITMAP, the MIIM_TYPE clears
-        * the MIIM_BITMAP style.  The fix is to reset both MIIM_BITMAP.
-        * Note, this does not happen on Windows 98.
-        */
-        bool restoreBitmap = false;
-        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (4, 10)) {
-            info.fMask = OS.MIIM_BITMAP;
-            OS.GetMenuItemInfo (hMenu, id, false, &info);
-            restoreBitmap = info.hbmpItem !is null || parent.foreground !is -1;
-        }
-
         /* Use the character encoding for the default locale */
         TCHAR[] buffer = StrToTCHARs (0, string, true);
         int byteCount = buffer.length * TCHAR.sizeof;
-        pszText = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
+        pszText = cast(TCHAR*)OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
         OS.MoveMemory (pszText, buffer.ptr, byteCount);
-        info.fMask = OS.MIIM_TYPE;
-        info.fType = widgetStyle ();
-        info.dwTypeData = pszText;
-        success = cast(bool) OS.SetMenuItemInfo (hMenu, id, false, &info);
-
         /*
-        * Restore the bitmap that was removed to work around a problem
-        * in GetMenuItemInfo() and menu items that have bitmaps set with
-        * MIIM_BITMAP.
+        * Bug in Windows 2000.  For some reason, when MIIM_TYPE is set
+        * on a menu item that also has MIIM_BITMAP, the MIIM_TYPE clears
+        * the MIIM_BITMAP style.  The fix is to use MIIM_STRING.
         */
         if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (4, 10)) {
-            if (restoreBitmap) {
-                info.fMask = OS.MIIM_BITMAP;
-                if (parent.foreground !is -1) {
-                    info.hbmpItem = OS.HBMMENU_CALLBACK;
-                } else {
-                    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
-                        info.hbmpItem = hBitmap;
-                    } else {
-                        info.hbmpItem = OS.HBMMENU_CALLBACK;
-                    }
-                }
-                success = cast(bool) OS.SetMenuItemInfo (hMenu, id, false, &info);
-            }
+            info.fMask = OS.MIIM_STRING;
+        } else {
+            info.fMask = OS.MIIM_TYPE;
+            info.fType = widgetStyle ();
         }
+        info.dwTypeData = pszText;
+        success = cast(bool) OS.SetMenuItemInfo (hMenu, id, false, &info);
     }
     if (pszText !is null) OS.HeapFree (hHeap, 0, pszText);
     if (!success) error (DWT.ERROR_CANNOT_SET_TEXT);
@@ -1151,7 +1125,7 @@
     return bits | OS.MFT_STRING;
 }
 
-LRESULT wmCommandChild (int wParam, int lParam) {
+LRESULT wmCommandChild (int /*long*/ wParam, int /*long*/ lParam) {
     if ((style & DWT.CHECK) !is 0) {
         setSelection (!getSelection ());
     } else {
@@ -1169,7 +1143,7 @@
     return null;
 }
 
-LRESULT wmDrawChild (int wParam, int lParam) {
+LRESULT wmDrawChild (int /*long*/ wParam, int /*long*/ lParam) {
     DRAWITEMSTRUCT* struct_ = cast(DRAWITEMSTRUCT*)lParam;
     //OS.MoveMemory (struct_, lParam, DRAWITEMSTRUCT.sizeof);
     if (image !is null) {
@@ -1192,7 +1166,7 @@
     return null;
 }
 
-LRESULT wmMeasureChild (int wParam, int lParam) {
+LRESULT wmMeasureChild (int /*long*/ wParam, int /*long*/ lParam) {
     MEASUREITEMSTRUCT* struct_ = cast(MEASUREITEMSTRUCT*)lParam;
     //OS.MoveMemory (struct_, lParam, MEASUREITEMSTRUCT.sizeof);
     int width = 0, height = 0;
--- a/dwt/widgets/MessageBox.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/MessageBox.d	Sat May 17 17:34:28 2008 +0200
@@ -42,6 +42,9 @@
  * </p>
  */
 public  class MessageBox : Dialog {
+
+    alias Dialog.checkStyle checkStyle;
+
     String message = "";
     private bool allowNullParent = false;
 
@@ -86,7 +89,7 @@
  * </ul>
  */
 public this (Shell parent, int style) {
-    super (parent, checkStyle (style));
+    super (parent, checkStyle (parent, checkStyle (style)));
     checkSubclass ();
 }
 
@@ -95,8 +98,7 @@
  +/
 public this (int style) {
     allowNullParent = true;
-    super (parent, checkStyle (style));
-    checkSubclass ();
+    this( null, style );
 }
 // PORT
 // actually, the parent can be null
@@ -107,7 +109,6 @@
 }
 
 static int checkStyle (int style) {
-    if ((style & (DWT.PRIMARY_MODAL | DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL)) is 0) style |= DWT.APPLICATION_MODAL;
     int mask = (DWT.YES | DWT.NO | DWT.OK | DWT.CANCEL | DWT.ABORT | DWT.RETRY | DWT.IGNORE);
     int bits = style & mask;
     if (bits is DWT.OK || bits is DWT.CANCEL || bits is (DWT.OK | DWT.CANCEL)) return style;
@@ -200,12 +201,12 @@
     * parent be temporarily modal.
     */
     HWND hwndOwner = parent !is null ? parent.handle : null;
-    Shell oldModal = null;
+    Dialog oldModal = null;
     Display display = null;
     if ((bits & OS.MB_TASKMODAL) !is 0) {
         display = ( allowNullParent && parent is null ) ? Display.getCurrent() : parent.getDisplay ();
-        oldModal = display.getModalDialogShell ();
-        display.setModalDialogShell (parent);
+        oldModal = display.getModalDialog ();
+        display.setModalDialog (this);
     }
 
     /* Open the message box */
@@ -216,7 +217,7 @@
 
     /* Clear the temporarily dialog modal parent */
     if ((bits & OS.MB_TASKMODAL) !is 0) {
-        display.setModalDialogShell (oldModal);
+        display.setModalDialog (oldModal);
     }
 
     /*
--- a/dwt/widgets/Monitor.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/Monitor.d	Sat May 17 17:34:28 2008 +0200
@@ -53,7 +53,8 @@
 
 /**
  * Returns a rectangle describing the receiver's size and location
- * relative to its device.
+ * relative to its device. Note that on multi-monitor systems the
+ * origin can be negative.
  *
  * @return the receiver's bounding rectangle
  */
--- a/dwt/widgets/ProgressBar.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/ProgressBar.d	Sat May 17 17:34:28 2008 +0200
@@ -65,7 +65,7 @@
             ProgressBarProc = lpWndClass.lpfnWndProc;
             /*
             * Feature in Windows.  The progress bar window class
-            * does not include CS_DBLCLKS.  This mean that these
+            * does not include CS_DBLCLKS.  This means that these
             * controls will not get double click messages such as
             * WM_LBUTTONDBLCLK.  The fix is to register a new
             * window class with CS_DBLCLKS.
@@ -210,6 +210,32 @@
     return OS.SendMessage (handle, OS.PBM_GETPOS, 0, 0);
 }
 
+/**
+ * Returns the state of the receiver. The value will be one of
+ * <code>NORMAL</code>, <code>ERROR</code> or <code>PAUSED</code>.
+ *
+ * @return the state 
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ * 
+ * @since 3.4
+ */
+public int getState () {
+    checkWidget ();
+    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+        int state = OS.SendMessage (handle, OS.PBM_GETSTATE, 0, 0);
+        switch (state) {
+            case OS.PBST_NORMAL: return DWT.NORMAL;
+            case OS.PBST_ERROR: return DWT.ERROR;
+            case OS.PBST_PAUSED: return DWT.PAUSED;
+        }
+    }
+    return DWT.NORMAL;
+}
+
 override void releaseWidget () {
     super.releaseWidget ();
     stopTimer ();
@@ -303,7 +329,52 @@
  */
 public void setSelection (int value) {
     checkWidget ();
+    /*
+    * Feature in Vista.  When the progress bar is not in
+    * a normal state, PBM_SETPOS does not set the position.
+    * This is undocumented.  The fix is to temporarily
+    * set the state to PBST_NORMAL, set the position, then
+    * reset the state.
+    */
+    int /*long*/ state = 0;
+    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+        state = OS.SendMessage (handle, OS.PBM_GETSTATE, 0, 0);
+        OS.SendMessage (handle, OS.PBM_SETSTATE, OS.PBST_NORMAL, 0);
+    }
     OS.SendMessage (handle, OS.PBM_SETPOS, value, 0);
+    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+        OS.SendMessage (handle, OS.PBM_SETSTATE, state, 0);
+    }
+}
+
+/**
+ * Sets the state of the receiver. The state is be one of
+ * <code>NORMAL</code>, <code>ERROR</code> or <code>PAUSED</code>.
+ *
+ * @param state the new state
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ * 
+ * @since 3.4
+ */
+public void setState (int state) {
+    checkWidget ();
+    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+        switch (state) {
+            case DWT.NORMAL:
+                OS.SendMessage (handle, OS.PBM_SETSTATE, OS.PBST_NORMAL, 0);
+                break;
+            case DWT.ERROR:
+                OS.SendMessage (handle, OS.PBM_SETSTATE, OS.PBST_ERROR, 0);
+                break;
+            case DWT.PAUSED:
+                OS.SendMessage (handle, OS.PBM_SETSTATE, OS.PBST_PAUSED, 0);
+                break;
+        }
+    }
 }
 
 override int widgetStyle () {
--- a/dwt/widgets/Sash.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/Sash.d	Sat May 17 17:34:28 2008 +0200
@@ -281,8 +281,7 @@
     /* Compute the banding rectangle */
     auto hwndTrack = parent.handle;
     POINT pt;
-    pt.x = cast(short) (lParam & 0xFFFF);
-    pt.y = cast(short) (lParam >> 16);
+    OS.POINTSTOPOINT (pt, lParam);
     RECT rect;
     OS.GetWindowRect (handle, &rect);
     OS.MapWindowPoints (handle, null, &pt, 1);
@@ -365,8 +364,7 @@
 
     /* Compute the banding rectangle */
     POINT pt;
-    pt.x = cast(short) (lParam & 0xFFFF);
-    pt.y = cast(short) (lParam >> 16);
+    OS.POINTSTOPOINT (pt, lParam);
     auto hwndTrack = parent.handle;
     OS.MapWindowPoints (handle, hwndTrack, &pt, 1);
     RECT rect, clientRect;
@@ -417,7 +415,7 @@
 override LRESULT WM_SETCURSOR (int wParam, int lParam) {
     LRESULT result = super.WM_SETCURSOR (wParam, lParam);
     if (result !is null) return result;
-    int hitTest = lParam & 0xFFFF;
+    int hitTest = cast(short) OS.LOWORD (lParam);
     if (hitTest is OS.HTCLIENT) {
         HCURSOR hCursor;
         if ((style & DWT.HORIZONTAL) !is 0) {
--- a/dwt/widgets/Scale.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/Scale.d	Sat May 17 17:34:28 2008 +0200
@@ -50,7 +50,7 @@
     alias Control.setBackgroundImage setBackgroundImage;
     alias Control.windowProc windowProc;
 
-    bool ignoreResize;
+    bool ignoreResize, ignoreSelection;
     private static /+const+/ WNDPROC TrackBarProc;
     static const TCHAR[] TrackBarClass = OS.TRACKBAR_CLASS;
 
@@ -68,7 +68,7 @@
             TrackBarProc = lpWndClass.lpfnWndProc;
             /*
             * Feature in Windows.  The track bar window class
-            * does not include CS_DBLCLKS.  This mean that these
+            * does not include CS_DBLCLKS.  This means that these
             * controls will not get double click messages such as
             * WM_LBUTTONDBLCLK.  The fix is to register a new
             * window class with CS_DBLCLKS.
@@ -248,7 +248,7 @@
  */
 public int getMinimum () {
     checkWidget ();
-    return OS.SendMessage (handle, OS.TBM_GETRANGEMIN, 0, 0);
+    return cast(int)OS.SendMessage (handle, OS.TBM_GETRANGEMIN, 0, 0);
 }
 
 /**
@@ -334,6 +334,33 @@
     ignoreResize = false;
 }
 
+void setBounds (int x, int y, int width, int height, int flags, bool defer) {
+    /*
+    * Bug in Windows.  If SetWindowPos() is called on a
+    * track bar with either SWP_DRAWFRAME, a new size,
+    * or both during mouse down, the track bar posts a
+    * WM_MOUSEMOVE message when the mouse has not moved.
+    * The window proc for the track bar uses WM_MOUSEMOVE
+    * to issue WM_HSCROLL or WM_SCROLL events to notify
+    * the application that the slider has changed.  The
+    * end result is that when the user requests a page
+    * scroll and the application resizes the track bar
+    * during the change notification, continuous stream
+    * of WM_MOUSEMOVE messages are generated and the
+    * thumb moves to the mouse position rather than
+    * scrolling by a page.  The fix is to clear the
+    * SWP_DRAWFRAME flag.
+    *
+    * NOTE:  There is no fix for the WM_MOUSEMOVE that
+    * is generated by a new size.  Clearing SWP_DRAWFRAME
+    * does not fix the problem.  However, it is unlikely
+    * that the programmer will resize the control during
+    * mouse down.
+    */
+    flags &= ~OS.SWP_DRAWFRAME;
+    super.setBounds (x, y, width, height, flags, true);
+}
+
 /**
  * Sets the amount that the receiver's value will be
  * modified by when the up/down (or right/left) arrows
@@ -452,6 +479,34 @@
 }
 
 override LRESULT WM_PAINT (int wParam, int lParam) {
+    LRESULT result = super.WM_MOUSEWHEEL (wParam, lParam);
+    if (result !is null) return result;
+    /*
+    * Bug in Windows.  When a track bar slider is changed
+    * from WM_MOUSEWHEEL, it does not always send either
+    * a WM_VSCROLL or M_HSCROLL to notify the application
+    * of the change.  The fix is to detect that the selection
+    * has changed and that notification has not been issued
+    * and send the selection event.
+    */
+    int oldPosition = OS.SendMessage (handle, OS.TBM_GETPOS, 0, 0);
+    ignoreSelection = true;
+    int /*long*/ code = callWindowProc (handle, OS.WM_MOUSEWHEEL, wParam, lParam);
+    ignoreSelection = false;
+    int newPosition = OS.SendMessage (handle, OS.TBM_GETPOS, 0, 0);
+    if (oldPosition !is newPosition) {
+        /*
+        * Send the event because WM_HSCROLL and WM_VSCROLL
+        * are sent from a modal message loop in windows that
+        * is active when the user is scrolling.
+        */
+        sendEvent (DWT.Selection);
+        // widget could be disposed at this point
+    }
+    return new LRESULT (code);
+}
+
+override LRESULT WM_MOUSEWHEEL (int wParam, int lParam) {
     /*
     * Bug in Windows.  For some reason, when WM_CTLCOLORSTATIC
     * is used to implement transparency and returns a NULL brush,
@@ -491,7 +546,7 @@
 override LRESULT wmScrollChild (int wParam, int lParam) {
 
     /* Do nothing when scrolling is ending */
-    int code = wParam & 0xFFFF;
+    int code = OS.LOWORD (wParam);
     switch (code) {
         case OS.TB_ENDTRACK:
         case OS.TB_THUMBPOSITION:
@@ -499,29 +554,31 @@
         default:
     }
 
-    Event event = new Event ();
-    /*
-    * This code is intentionally commented.  The event
-    * detail field is not currently supported on all
-    * platforms.
-    */
-//  switch (code) {
-//      case OS.TB_TOP:         event.detail = DWT.HOME;  break;
-//      case OS.TB_BOTTOM:      event.detail = DWT.END;  break;
-//      case OS.TB_LINEDOWN:    event.detail = DWT.ARROW_DOWN;  break;
-//      case OS.TB_LINEUP:      event.detail = DWT.ARROW_UP;  break;
-//      case OS.TB_PAGEDOWN:    event.detail = DWT.PAGE_DOWN;  break;
-//      case OS.TB_PAGEUP:      event.detail = DWT.PAGE_UP;  break;
+    if (!ignoreSelection) {
+        Event event = new Event ();
+        /*
+        * This code is intentionally commented.  The event
+        * detail field is not currently supported on all
+        * platforms.
+        */
+//      switch (code) {
+//          case OS.TB_TOP:         event.detail = DWT.HOME;  break;
+//          case OS.TB_BOTTOM:      event.detail = DWT.END;  break;
+//          case OS.TB_LINEDOWN:    event.detail = DWT.ARROW_DOWN;  break;
+//          case OS.TB_LINEUP:      event.detail = DWT.ARROW_UP;  break;
+//          case OS.TB_PAGEDOWN:    event.detail = DWT.PAGE_DOWN;  break;
+//          case OS.TB_PAGEUP:      event.detail = DWT.PAGE_UP;  break;
 //      default:
-//  }
+//      }
 
-    /*
-    * Send the event because WM_HSCROLL and WM_VSCROLL
-    * are sent from a modal message loop in windows that
-    * is active when the user is scrolling.
-    */
-    sendEvent (DWT.Selection, event);
-    // widget could be disposed at this point
+        /*
+        * Send the event because WM_HSCROLL and WM_VSCROLL
+        * are sent from a modal message loop in windows that
+        * is active when the user is scrolling.
+        */
+        sendEvent (DWT.Selection, event);
+        // widget could be disposed at this point
+    }
     return null;
 }
 
--- a/dwt/widgets/ScrollBar.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/ScrollBar.d	Sat May 17 17:34:28 2008 +0200
@@ -207,7 +207,10 @@
     } else {
         OS.ShowScrollBar (hwnd, type, false);
     }
+    parent.destroyScrollBar (style);
     releaseHandle ();
+    //This code is intentionally commented
+    //parent.sendEvent (DWT.Resize);
 }
 
 Rectangle getBounds () {
@@ -433,6 +436,13 @@
  */
 public bool getVisible () {
     checkWidget();
+    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION(4, 10)) {
+        SCROLLBARINFO psbi;
+        psbi.cbSize = SCROLLBARINFO.sizeof;
+        int idObject = (style & DWT.VERTICAL) !is 0 ? OS.OBJID_VSCROLL : OS.OBJID_HSCROLL;
+        OS.GetScrollBarInfo (hwndScrollBar (), idObject, &psbi);
+        return (psbi.rgstate [0] & OS.STATE_SYSTEM_INVISIBLE) is 0;
+    }
     return (state & HIDDEN) is 0;
 }
 
@@ -653,7 +663,27 @@
     * scroll bar operation is performed), the opposite scroll
     * bar draws.  The fix is to hide both scroll bars.
     */
-    if ((state & (DISABLED | HIDDEN)) !is 0) fRedraw = false;
+    bool barVisible = false;
+    bool visible = getVisible ();
+
+    /*
+    * This line is intentionally commented.  Currently
+    * always show scrollbar as being enabled and visible.
+    */
+//  if (OS.IsWinCE) error (DWT.ERROR_NOT_IMPLEMENTED);
+    ScrollBar bar = null;
+    if (!OS.IsWinCE) {
+        switch (flags) {
+            case OS.SB_HORZ:
+                bar = parent.getVerticalBar ();
+                break;
+            case OS.SB_VERT:
+                bar = parent.getHorizontalBar ();
+                break;
+        }
+        barVisible = bar !is null && bar.getVisible ();
+    }
+    if (!visible || (state & DISABLED) !is 0) fRedraw = false;
     bool result = cast(bool) OS.SetScrollInfo (hwnd, flags, info, fRedraw);
 
     /*
@@ -665,25 +695,31 @@
     * is performed), the scroll bar draws.  The fix is
     * to hide the scroll bar (again) when already hidden.
     */
-    if ((state & HIDDEN) !is 0) {
+    if (!visible) {
         /*
         * This line is intentionally commented.  Currently
         * always show scrollbar as being enabled and visible.
         */
 //      if (OS.IsWinCE) error (DWT.ERROR_NOT_IMPLEMENTED);
         if (!OS.IsWinCE) {
-            ScrollBar bar = null;
-            switch (flags) {
-                case OS.SB_HORZ:
-                    bar = parent.getVerticalBar ();
-                    break;
-                case OS.SB_VERT:
-                    bar = parent.getHorizontalBar ();
-                    break;
-                default:
-            }
-            bool both = bar !is null && !bar.getVisible ();
-            OS.ShowScrollBar (hwnd, both ? OS.SB_BOTH : flags, false);
+            OS.ShowScrollBar (hwnd, !barVisible ? OS.SB_BOTH : flags, false);
+        }
+    }
+
+    /*
+    * Bug in Windows.  When only one scroll bar is visible,
+    * and the thumb changes using SIF_RANGE or SIF_PAGE
+    * from being visible to hidden, the opposite scroll
+    * bar is incorrectly made visible.  The next time the
+    * parent is resized (or another scroll bar operation
+    * is performed), the opposite scroll bar draws.  The
+    * fix is to hide the opposite scroll bar again.
+    *
+    * NOTE: This problem only happens on Vista
+    */
+    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+        if (visible && bar !is null && !barVisible) {
+            OS.ShowScrollBar (hwnd, flags is OS.SB_HORZ ? OS.SB_VERT : OS.SB_HORZ, false);
         }
     }
 
@@ -820,8 +856,7 @@
  */
 public void setVisible (bool visible) {
     checkWidget();
-    bool isVisible = (state & HIDDEN) is 0;
-    if (isVisible is visible) return;
+    if (visible is getVisible ()) return;
 
     /*
     * On Windows CE, use SIF_DISABLENOSCROLL to show and
@@ -898,11 +933,11 @@
     }
 }
 
-LRESULT wmScrollChild (int wParam, int lParam) {
+LRESULT wmScrollChild (int /*long*/ wParam, int /*long*/ lParam) {
 trc(__LINE__);
 
     /* Do nothing when scrolling is ending */
-    int code = wParam & 0xFFFF;
+    int code = OS.LOWORD (wParam);
     if (code is OS.SB_ENDSCROLL) return null;
 
     /*
--- a/dwt/widgets/Scrollable.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/Scrollable.d	Sat May 17 17:34:28 2008 +0200
@@ -12,16 +12,20 @@
  *******************************************************************************/
 module dwt.widgets.Scrollable;
 
-import dwt.widgets.Widget;
-import dwt.widgets.Event;
-import dwt.widgets.Control;
-import dwt.widgets.ScrollBar;
-import dwt.widgets.Composite;
 import dwt.DWT;
 import dwt.DWTException;
+
 import dwt.graphics.Rectangle;
+
 import dwt.internal.win32.OS;
 
+import dwt.widgets.Composite;
+import dwt.widgets.Control;
+import dwt.widgets.Decorations;
+import dwt.widgets.Event;
+import dwt.widgets.ScrollBar;
+import dwt.widgets.Widget;
+
 import dwt.dwthelper.utils;
 import tango.util.log.Trace;
 void trc( long line ){
@@ -149,6 +153,20 @@
     if ((style & DWT.V_SCROLL) !is 0) verticalBar = createScrollBar (DWT.V_SCROLL);
 }
 
+void destroyScrollBar (int type) {
+    auto hwnd = scrolledHandle ();
+    int bits = OS.GetWindowLong (hwnd, OS.GWL_STYLE);
+    if ((type & DWT.HORIZONTAL) !is 0) {
+        style &= ~DWT.H_SCROLL;
+        bits &= ~OS.WS_HSCROLL;
+    }
+    if ((type & DWT.VERTICAL) !is 0) {
+        style &= ~DWT.V_SCROLL;
+        bits &= ~OS.WS_VSCROLL;
+    }
+    OS.SetWindowLong (hwnd, OS.GWL_STYLE, bits);
+}
+
 /**
  * Returns a rectangle which describes the area of the
  * receiver which is capable of displaying data (that is,
@@ -278,9 +296,9 @@
 
 override LRESULT WM_MOUSEWHEEL (int wParam, int lParam) {
 trc(__LINE__);
+    int scrollRemainder = display.scrollRemainder;
     LRESULT result = super.WM_MOUSEWHEEL (wParam, lParam);
     if (result !is null) return result;
-
     /*
     * Translate WM_MOUSEWHEEL to WM_VSCROLL or WM_HSCROLL.
     */
@@ -288,27 +306,37 @@
         if ((wParam & (OS.MK_SHIFT | OS.MK_CONTROL)) !is 0) return result;
         bool vertical = verticalBar !is null && verticalBar.getEnabled ();
         bool horizontal = horizontalBar !is null && horizontalBar.getEnabled ();
-        int msg = (vertical) ? OS.WM_VSCROLL : (horizontal) ? OS.WM_HSCROLL : 0;
+        int msg = vertical ? OS.WM_VSCROLL : horizontal ? OS.WM_HSCROLL : 0;
         if (msg is 0) return result;
-        int value;
-        OS.SystemParametersInfo (OS.SPI_GETWHEELSCROLLLINES, 0, &value, 0);
-        int delta = cast(short) (wParam >> 16);
-        int code = 0, count = 0;
-        if (value  is OS.WHEEL_PAGESCROLL) {
-            code = delta < 0 ? OS.SB_PAGEDOWN : OS.SB_PAGEUP;
-            count = Math.abs (delta / OS.WHEEL_DELTA);
+        int linesToScroll;
+        OS.SystemParametersInfo (OS.SPI_GETWHEELSCROLLLINES, 0, &linesToScroll, 0);
+        int delta = OS.GET_WHEEL_DELTA_WPARAM (wParam);
+        bool pageScroll = linesToScroll is OS.WHEEL_PAGESCROLL;
+        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+            ScrollBar bar = vertical ? verticalBar : horizontalBar;
+            SCROLLINFO info;
+            info.cbSize = SCROLLINFO.sizeof;
+            info.fMask = OS.SIF_POS;
+            OS.GetScrollInfo (handle, bar.scrollBarType (), &info);
+            if (vertical && !pageScroll) delta *= linesToScroll;
+            int increment = pageScroll ? bar.getPageIncrement () : bar.getIncrement ();
+            info.nPos -=  increment * delta / OS.WHEEL_DELTA;
+            OS.SetScrollInfo (handle, bar.scrollBarType (), &info, true);
+            OS.SendMessage (handle, msg, OS.SB_THUMBPOSITION, 0);
         } else {
-            code = delta < 0 ? OS.SB_LINEDOWN : OS.SB_LINEUP;
-            delta = Math.abs (delta);
-            if (delta < OS.WHEEL_DELTA) return result;
-            if (msg is OS.WM_VSCROLL) {
-                count = value  * delta / OS.WHEEL_DELTA;
+            int code = 0;
+            if (pageScroll) {
+                code = delta < 0 ? OS.SB_PAGEDOWN : OS.SB_PAGEUP;
             } else {
-                count = delta / OS.WHEEL_DELTA;
+                code = delta < 0 ? OS.SB_LINEDOWN : OS.SB_LINEUP;
+                if (msg is OS.WM_VSCROLL) delta *= linesToScroll;
             }
-        }
-        for (int i=0; i<count; i++) {
-            OS.SendMessage (handle, msg, code, 0);
+            /* Check if the delta and the remainder have the same direction (sign) */
+            if ((delta ^ scrollRemainder) >= 0) delta += scrollRemainder;
+            int count = Math.abs (delta) / OS.WHEEL_DELTA;
+            for (int i=0; i<count; i++) {
+                OS.SendMessage (handle, msg, code, 0);
+            }
         }
         return LRESULT.ZERO;
     }
@@ -326,7 +354,7 @@
     */
     int vPosition = verticalBar is null ? 0 : verticalBar.getSelection ();
     int hPosition = horizontalBar is null ? 0 : horizontalBar.getSelection ();
-    int code = callWindowProc (handle, OS.WM_MOUSEWHEEL, wParam, lParam);
+    int /*long*/ code = callWindowProc (handle, OS.WM_MOUSEWHEEL, wParam, lParam);
     if (verticalBar !is null) {
         int position = verticalBar.getSelection ();
         if (position !is vPosition) {
@@ -348,7 +376,7 @@
 
 override LRESULT WM_SIZE (int wParam, int lParam) {
 trc(__LINE__);
-    int code = callWindowProc (handle, OS.WM_SIZE, wParam, lParam);
+    int /*long*/ code = callWindowProc (handle, OS.WM_SIZE, wParam, lParam);
     super.WM_SIZE (wParam, lParam);
     // widget may be disposed at this point
     if (code is 0) return LRESULT.ZERO;
@@ -372,8 +400,64 @@
     return result;
 }
 
-LRESULT wmScroll (ScrollBar bar, bool update, HWND hwnd, int msg, int wParam, int lParam) {
-trc(__LINE__);
+LRESULT wmNCPaint (HWND hwnd, int /*long*/ wParam, int /*long*/ lParam) {
+    LRESULT result = super.wmNCPaint (hwnd, wParam, lParam);
+    if (result !is null) return result;
+    /*
+    * Bug in Windows.  On XP only (not Vista), Windows sometimes
+    * does not redraw the bottom right corner of a window that
+    * has scroll bars, causing pixel corruption.  The fix is to
+    * always draw the corner.
+    */
+    if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
+        if (!OS.IsWinCE && OS.WIN32_VERSION < OS.VERSION (6, 0)) {
+            int bits1 = OS.GetWindowLong (hwnd, OS.GWL_STYLE);
+            if ((bits1 & (OS.WS_HSCROLL | OS.WS_VSCROLL)) !is 0) {
+                RECT windowRect;
+                OS.GetWindowRect (hwnd, &windowRect);
+                RECT trimRect;
+                int bits2 = OS.GetWindowLong (hwnd, OS.GWL_EXSTYLE);
+                OS.AdjustWindowRectEx (&trimRect, bits1, false, bits2);
+                bool hVisible = false, vVisible = false;
+                SCROLLBARINFO psbi;
+                psbi.cbSize = SCROLLBARINFO.sizeof;
+                if (OS.GetScrollBarInfo (hwnd, OS.OBJID_HSCROLL, &psbi)) {
+                    hVisible = (psbi.rgstate [0] & OS.STATE_SYSTEM_INVISIBLE) is 0;
+                }
+                if (OS.GetScrollBarInfo (hwnd, OS.OBJID_VSCROLL, &psbi)) {
+                    vVisible = (psbi.rgstate [0] & OS.STATE_SYSTEM_INVISIBLE) is 0;
+                }
+                RECT cornerRect;
+                cornerRect.right = windowRect.right - windowRect.left - trimRect.right;
+                cornerRect.bottom = windowRect.bottom - windowRect.top - trimRect.bottom;
+                cornerRect.left = cornerRect.right - (hVisible ? OS.GetSystemMetrics (OS.SM_CXVSCROLL) : 0);
+                cornerRect.top = cornerRect.bottom - (vVisible ? OS.GetSystemMetrics (OS.SM_CYHSCROLL) : 0);
+                if (cornerRect.left !is cornerRect.right && cornerRect.top !is cornerRect.bottom) {
+                    auto hDC = OS.GetWindowDC (hwnd);
+                    OS.FillRect (hDC, &cornerRect, cast(HANDLE)( OS.COLOR_BTNFACE + 1));
+                    Decorations shell = menuShell ();
+                    if ((shell.style & DWT.RESIZE) !is 0) {
+                        auto hwndScroll = shell.scrolledHandle ();
+                        bool drawGripper = hwnd is hwndScroll;
+                        if (!drawGripper) {
+                            RECT shellRect;
+                            OS.GetClientRect (hwndScroll, &shellRect);
+                            OS.MapWindowPoints (hwndScroll, null, cast(POINT*)&shellRect, 2);
+                            drawGripper = shellRect.right is windowRect.right && shellRect.bottom is windowRect.bottom;
+                        }
+                        if (drawGripper) {
+                            OS.DrawThemeBackground (display.hScrollBarTheme(), hDC, OS.SBP_SIZEBOX, 0, &cornerRect, null);
+                        }
+                    }
+                    OS.ReleaseDC (hwnd, hDC);
+                }
+            }
+        }
+    }
+    return result;
+}
+
+LRESULT wmScroll (ScrollBar bar, bool update, HWND hwnd, int msg, int /*long*/ wParam, int /*long*/ lParam) {
     LRESULT result = null;
     if (update) {
         int type = msg is OS.WM_HSCROLL ? OS.SB_HORZ : OS.SB_VERT;
@@ -382,7 +466,7 @@
         info.fMask = OS.SIF_TRACKPOS | OS.SIF_POS | OS.SIF_RANGE;
         OS.GetScrollInfo (hwnd, type, &info);
         info.fMask = OS.SIF_POS;
-        int code = wParam & 0xFFFF;
+        int code = OS.LOWORD (wParam);
         switch (code) {
             case OS.SB_ENDSCROLL:  return null;
             case OS.SB_THUMBPOSITION:
@@ -419,7 +503,7 @@
         }
         OS.SetScrollInfo (hwnd, type, &info, true);
     } else {
-        int code = callWindowProc (hwnd, msg, wParam, lParam);
+        int /*long*/ code = callWindowProc (hwnd, msg, wParam, lParam);
         result = code is 0 ? LRESULT.ZERO : new LRESULT (code);
     }
     bar.wmScrollChild (wParam, lParam);
--- a/dwt/widgets/Shell.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/Shell.d	Sat May 17 17:34:28 2008 +0200
@@ -16,6 +16,7 @@
 import dwt.DWTException;
 import dwt.events.ShellListener;
 import dwt.graphics.Cursor;
+import dwt.graphics.GC;
 import dwt.graphics.Point;
 import dwt.graphics.Rectangle;
 import dwt.graphics.Region;
@@ -28,6 +29,7 @@
 import dwt.widgets.ToolTip;
 import dwt.widgets.Display;
 import dwt.widgets.TypedListener;
+import dwt.widgets.Event;
 
 import dwt.dwthelper.utils;
 
@@ -147,23 +149,22 @@
     HANDLE balloonTipHandle_;
     int minWidth = DWT.DEFAULT, minHeight = DWT.DEFAULT;
     HBRUSH [] brushes;
-    bool showWithParent;
+    bool showWithParent, fullScreen, wasMaximized;
     String toolTitle, balloonTitle;
     HICON toolIcon;
     HICON balloonIcon;
     WNDPROC windowProc_;
-    Control lastActive, lockToolTipControl;
+    Control lastActive;
     static if( OS.IsWinCE ){
         SHACTIVATEINFO psai;
     }
-    Region region;
     static /+const+/ WNDPROC ToolTipProc;
     static /+const+/ WNDPROC DialogProc;
     static if( OS.IsWinCE ){
-        static const TCHAR[] DialogClass = "Dialog\0";
+        static const TCHAR[] DialogClass = "Dialog\0"w;
     }
     else{
-        static const TCHAR[] DialogClass = "#32770\0";
+        static const TCHAR[] DialogClass = "#32770\0"w;
     }
     const static int [] SYSTEM_COLORS = [
         OS.COLOR_BTNFACE,
@@ -413,7 +414,8 @@
 }
 
 /**
- * Invokes platform specific functionality to allocate a new shell.
+ * Invokes platform specific functionality to allocate a new shell
+ * that is embedded.
  * <p>
  * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
  * API for <code>Shell</code>. It is marked public only so that it
@@ -430,12 +432,30 @@
     return new Shell (display, null, DWT.NO_TRIM, handle, true);
 }
 
+/**
+ * Invokes platform specific functionality to allocate a new shell
+ * that is not embedded.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Shell</code>. It is marked public only so that it
+ * can be shared within the packages provided by DWT. It is not
+ * available on all platforms, and should never be called from
+ * application code.
+ * </p>
+ *
+ * @param display the display for the shell
+ * @param handle the handle for the shell
+ * @return a new shell object containing the specified display and handle
+ *
+ * @since 3.3
+ */
 public static Shell internal_new (Display display, HWND handle) {
     return new Shell (display, null, DWT.NO_TRIM, handle, false);
 }
 
 static int checkStyle (int style) {
     style = Decorations.checkStyle (style);
+    style &= ~DWT.TRANSPARENT;
     int mask = DWT.SYSTEM_MODAL | DWT.APPLICATION_MODAL | DWT.PRIMARY_MODAL;
     int bits = style & ~mask;
     if ((style & DWT.SYSTEM_MODAL) !is 0) return bits | DWT.SYSTEM_MODAL;
@@ -531,7 +551,7 @@
         0,
         OS.TOOLTIPS_CLASS.ptr,
         null,
-        OS.TTS_ALWAYSTIP | OS.TTS_BALLOON,
+        OS.TTS_ALWAYSTIP | OS.TTS_NOPREFIX | OS.TTS_BALLOON,
         OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
         handle,
         null,
@@ -539,7 +559,7 @@
         null);
     if (balloonTipHandle_ is null) error (DWT.ERROR_NO_HANDLES);
     if (ToolTipProc is null) {
-        ToolTipProc = cast(WNDPROC) OS.GetWindowLong (balloonTipHandle_, OS.GWL_WNDPROC);
+        ToolTipProc = cast(WNDPROC) OS.GetWindowLongPtr (balloonTipHandle_, OS.GWLP_WNDPROC);
     }
     /*
     * Feature in Windows.  Despite the fact that the
@@ -550,7 +570,7 @@
     */
     OS.SendMessage (balloonTipHandle_, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF);
     display.addControl (balloonTipHandle_, this);
-    OS.SetWindowLong (balloonTipHandle_, OS.GWL_WNDPROC, display.windowProc);
+    OS.SetWindowLongPtr (balloonTipHandle_, OS.GWLP_WNDPROC, display.windowProc);
 }
 
 override void createHandle () {
@@ -639,7 +659,7 @@
         0,
         OS.TOOLTIPS_CLASS.ptr,
         null,
-        OS.TTS_ALWAYSTIP,
+        OS.TTS_ALWAYSTIP | OS.TTS_NOPREFIX,
         OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
         handle,
         null,
@@ -647,7 +667,7 @@
         null);
     if (toolTipHandle_ is null) error (DWT.ERROR_NO_HANDLES);
     if (ToolTipProc is null) {
-        ToolTipProc = cast(WNDPROC) OS.GetWindowLong (toolTipHandle_, OS.GWL_WNDPROC);
+        ToolTipProc = cast(WNDPROC) OS.GetWindowLongPtr (toolTipHandle_, OS.GWLP_WNDPROC);
     }
     /*
     * Feature in Windows.  Despite the fact that the
@@ -658,7 +678,7 @@
     */
     OS.SendMessage (toolTipHandle_, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF);
     display.addControl (toolTipHandle_, this);
-    OS.SetWindowLong (toolTipHandle_, OS.GWL_WNDPROC, display.windowProc);
+    OS.SetWindowLongPtr (toolTipHandle_, OS.GWLP_WNDPROC, display.windowProc);
 }
 
 override void deregister () {
@@ -864,6 +884,29 @@
     /* Do nothing */
 }
 
+/**
+ * Returns the receiver's alpha value.
+ *
+ * @return the alpha value
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @since 3.4
+ */
+public int getAlpha () {
+    checkWidget ();
+    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 1)) {
+        ubyte [1] pbAlpha;
+        if (OS.GetLayeredWindowAttributes (handle, null, pbAlpha.ptr, null)) {
+            return pbAlpha [0] & 0xFF;
+        }
+    }
+    return 0xFF;
+}
+
 override public Rectangle getBounds () {
     checkWidget ();
     static if (!OS.IsWinCE) {
@@ -906,6 +949,25 @@
 }
 
 /**
+ * Returns <code>true</code> if the receiver is currently
+ * in fullscreen state, and false otherwise.
+ * <p>
+ *
+ * @return the fullscreen state
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @since 3.4
+ */
+public bool getFullScreen () {
+    checkWidget();
+    return fullScreen;
+}
+
+/**
  * Returns the receiver's input method editor mode. This
  * will be the result of bitwise OR'ing together one or
  * more of the following constants defined in class
@@ -951,6 +1013,11 @@
     return new Point (rect.left, rect.top);
 }
 
+public bool getMaximized () {
+    checkWidget ();
+    return !fullScreen && super.getMaximized ();
+}
+
 /**
  * Returns a point describing the minimum receiver's size. The
  * x coordinate of the result is the minimum width of the receiver.
@@ -1003,6 +1070,7 @@
  *
  */
 public Region getRegion () {
+    /* This method is needed for the @since 3.0 Javadoc */
     checkWidget ();
     return region;
 }
@@ -1151,6 +1219,13 @@
     if (!restoreFocus () && !traverseGroup (true)) setFocus ();
 }
 
+public bool print (GC gc) {
+    checkWidget ();
+    if (gc is null) error (DWT.ERROR_NULL_ARGUMENT);
+    if (gc.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT);
+    return false;
+}
+
 override void register () {
     super.register ();
     if (toolTipHandle_ !is null) display.addControl (toolTipHandle_, this);
@@ -1210,9 +1285,7 @@
         if (hIMC !is null) OS.ImmDestroyContext (hIMC);
     }
     lastActive = null;
-    region = null;
     toolTitle = balloonTitle = null;
-    lockToolTipControl = null;
 }
 
 override void removeMenu (Menu menu) {
@@ -1262,6 +1335,11 @@
     return (result > 0) ? LRESULT.ONE : LRESULT.ZERO;
 }
 
+bool sendKeyEvent (int type, int msg, int /*long*/ wParam, int /*long*/ lParam, Event event) {
+    if (!isEnabled () || !isActive ()) return false;
+    return super.sendKeyEvent (type, msg, wParam, lParam, event);
+}
+
 /**
  * If the receiver is visible, moves it to the top of the
  * drawing order for the display on which it was created
@@ -1327,7 +1405,52 @@
     }
 }
 
+/**
+ * Sets the receiver's alpha value.
+ * <p>
+ * This operation requires the operating system's advanced
+ * widgets subsystem which may not be available on some
+ * platforms.
+ * </p>
+ * @param alpha the alpha value
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @since 3.4
+ */
+public void setAlpha (int alpha) {
+    checkWidget ();
+    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 1)) {
+        alpha &= 0xFF;
+        int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
+        if (alpha is 0xFF) {
+            OS.SetWindowLong (handle, OS.GWL_EXSTYLE, bits & ~OS.WS_EX_LAYERED);
+            int flags = OS.RDW_ERASE | OS.RDW_INVALIDATE | OS.RDW_FRAME | OS.RDW_ALLCHILDREN;
+            OS.RedrawWindow (handle, null, null, flags);
+        } else {
+            OS.SetWindowLong (handle, OS.GWL_EXSTYLE, bits | OS.WS_EX_LAYERED);
+            OS.SetLayeredWindowAttributes (handle, 0, cast(byte)alpha, OS.LWA_ALPHA);
+        }
+    }
+}
+
 override void setBounds (int x, int y, int width, int height, int flags, bool defer) {
+    if (fullScreen) setFullScreen (false);
+    /*
+    * Bug in Windows.  When a window has alpha and
+    * SetWindowPos() is called with SWP_DRAWFRAME,
+    * the contents of the window are copied rather
+    * than allowing the windows underneath to draw.
+    * This causes pixel corruption.  The fix is to
+    * clear the SWP_DRAWFRAME bits.
+    */
+    int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
+    if ((bits & OS.WS_EX_LAYERED) !is 0) {
+        flags &= ~OS.SWP_DRAWFRAME;
+    }
     super.setBounds (x, y, width, height, flags, false);
 }
 
@@ -1341,6 +1464,54 @@
 }
 
 /**
+ * Sets the full screen state of the receiver.
+ * If the argument is <code>true</code> causes the receiver
+ * to switch to the full screen state, and if the argument is
+ * <code>false</code> and the receiver was previously switched
+ * into full screen state, causes the receiver to switch back
+ * to either the maximmized or normal states.
+ * <p>
+ * Note: The result of intermixing calls to <code>setFullScreen(true)</code>,
+ * <code>setMaximized(true)</code> and <code>setMinimized(true)</code> will
+ * vary by platform. Typically, the behavior will match the platform user's
+ * expectations, but not always. This should be avoided if possible.
+ * </p>
+ *
+ * @param fullScreen the new fullscreen state
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @since 3.4
+ */
+public void setFullScreen (bool fullScreen) {
+    checkWidget();
+    if (this.fullScreen is fullScreen) return;
+    int stateFlags = fullScreen ? OS.SW_SHOWMAXIMIZED : OS.SW_RESTORE;
+    int styleFlags = OS.GetWindowLong (handle, OS.GWL_STYLE);
+    int mask = DWT.TITLE | DWT.CLOSE | DWT.MIN | DWT.MAX;
+    if ((style & mask) !is 0) {
+        if (fullScreen) {
+            styleFlags = styleFlags & ~OS.WS_CAPTION;
+        } else {
+            styleFlags = styleFlags | OS.WS_CAPTION;
+        }
+    }
+    if (fullScreen) wasMaximized = getMaximized ();
+    bool visible = isVisible ();
+    OS.SetWindowLong (handle, OS.GWL_STYLE, styleFlags);
+    if (wasMaximized) {
+        OS.ShowWindow (handle, OS.SW_HIDE);
+        stateFlags = OS.SW_SHOWMAXIMIZED;
+    }
+    if (visible) OS.ShowWindow (handle, stateFlags);
+    OS.UpdateWindow (handle);
+    this.fullScreen = fullScreen;
+}
+
+/**
  * Sets the input method editor mode to the argument which
  * should be the result of bitwise OR'ing together one or more
  * of the following constants defined in class <code>DWT</code>:
@@ -1359,7 +1530,7 @@
 public void setImeInputMode (int mode) {
     checkWidget ();
     if (!OS.IsDBLocale) return;
-    bool imeOn = mode !is DWT.NONE && mode !is DWT.ROMAN;
+    bool imeOn = mode !is DWT.NONE;
     auto hIMC = OS.ImmGetContext (handle);
     OS.ImmSetOpenStatus (hIMC, imeOn);
     if (imeOn) {
@@ -1376,7 +1547,7 @@
                     oldBits = OS.IME_CMODE_KATAKANA;
                 }
             }
-            if ((mode & DWT.DBCS) !is 0) {
+            if ((mode & (DWT.DBCS | DWT.NATIVE)) !is 0) {
                 newBits |= OS.IME_CMODE_FULLSHAPE;
             } else {
                 oldBits |= OS.IME_CMODE_FULLSHAPE;
@@ -1386,7 +1557,8 @@
             } else {
                 oldBits |= OS.IME_CMODE_ROMAN;
             }
-            lpfdwConversion |= newBits;  lpfdwConversion &= ~oldBits;
+            lpfdwConversion |= newBits;
+            lpfdwConversion &= ~oldBits;
             OS.ImmSetConversionStatus (hIMC, lpfdwConversion, lpfdwSentence);
         }
     }
@@ -1492,14 +1664,7 @@
 public void setRegion (Region region) {
     checkWidget ();
     if ((style & DWT.NO_TRIM) is 0) return;
-    if (region !is null && region.isDisposed()) error (DWT.ERROR_INVALID_ARGUMENT);
-    HRGN hRegion;
-    if (region !is null) {
-        hRegion = OS.CreateRectRgn (0, 0, 0, 0);
-        OS.CombineRgn (hRegion, region.handle, hRegion, OS.RGN_OR);
-    }
-    OS.SetWindowRgn (handle, hRegion, true);
-    this.region = region;
+    super.setRegion (region);
 }
 
 void setToolTipText (HWND hwnd, String text) {
@@ -1522,7 +1687,7 @@
     }
 }
 
-void setToolTipText (NMTTDISPINFO* lpnmtdi, byte [] buffer) {
+void setToolTipText (NMTTDISPINFO* lpnmtdi, char [] buffer) {
     /*
     * Ensure that the current position of the mouse
     * is inside the client area of the shell.  This
@@ -1538,7 +1703,7 @@
     lpnmtdi.lpszText = lpstrTip;
 }
 
-void setToolTipText (NMTTDISPINFO* lpnmtdi, char [] buffer) {
+void setToolTipText (NMTTDISPINFO* lpnmtdi, wchar [] buffer) {
     /*
     * Ensure that the current position of the mouse
     * is inside the client area of the shell.  This
@@ -1548,7 +1713,7 @@
     if (!hasCursor ()) return;
     auto hHeap = OS.GetProcessHeap ();
     if (lpstrTip !is null) OS.HeapFree (hHeap, 0, lpstrTip);
-    TCHAR[] charz = StrToTCHARs( 0, buffer );
+    TCHAR[] charz = buffer;//StrToTCHARs( 0, buffer );
     int byteCount = charz.length * TCHAR.sizeof;
     lpstrTip = cast(TCHAR*)OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
     OS.MoveMemory (lpstrTip, charz.ptr, byteCount);
@@ -1605,12 +1770,6 @@
 
 override public void setVisible (bool visible) {
     checkWidget ();
-    if (drawCount !is 0) {
-        if (((state & HIDDEN) is 0) is visible) return;
-    } else {
-        if (visible is OS.IsWindowVisible (handle)) return;
-    }
-
     /*
     * Feature in Windows.  When ShowWindow() is called used to hide
     * a window, Windows attempts to give focus to the parent. If the
@@ -1624,6 +1783,9 @@
     if ((style & mask) !is 0) {
         if (visible) {
             display.setModalShell (this);
+            if ((style & (DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL)) !is 0) {
+                display.setModalDialog (null);
+            }
             Control control = display._getFocusControl ();
             if (control !is null && !control.isActive ()) {
                 bringToTop ();
@@ -1656,22 +1818,41 @@
     if (!visible) fixActiveShell ();
     super.setVisible (visible);
     if (isDisposed ()) return;
-    if (showWithParent is visible) return;
-    showWithParent = visible;
+    if (showWithParent !is visible) {
+        showWithParent = visible;
+        if (visible) {
+            static if (!OS.IsWinCE) OS.ShowOwnedPopups (handle, true);
+        }
+    }
+
+    /* Make the splash screen appear in the task bar */
     if (visible) {
-        static if (!OS.IsWinCE) OS.ShowOwnedPopups (handle, true);
+        if (parent !is null && (parent.state & FOREIGN_HANDLE) !is 0) {
+            auto hwndParent = parent.handle;
+            int style = OS.GetWindowLong (hwndParent, OS.GWL_EXSTYLE);
+            if ((style & OS.WS_EX_TOOLWINDOW) !is 0) {
+                OS.SetWindowLong (hwndParent, OS.GWL_EXSTYLE, style & ~OS.WS_EX_TOOLWINDOW);
+                /*
+                * Bug in Windows.  The window does not show in the task bar when
+                * WS_EX_TOOLWINDOW is removed after the window has already been shown.
+                * The fix is to hide and shown the shell.
+                */
+                OS.ShowWindow (hwndParent, OS.SW_HIDE);
+                OS.ShowWindow (hwndParent, OS.SW_RESTORE);
+            }
+        }
     }
 }
 
 override void subclass () {
     super.subclass ();
     if (ToolTipProc !is null) {
-        int newProc = display.windowProc;
+        int /*long*/ newProc = display.windowProc;
         if (toolTipHandle_ !is null) {
-            OS.SetWindowLong (toolTipHandle_, OS.GWL_WNDPROC, newProc);
+            OS.SetWindowLongPtr (toolTipHandle_, OS.GWLP_WNDPROC, newProc);
         }
         if (balloonTipHandle_ !is null) {
-            OS.SetWindowLong (balloonTipHandle_, OS.GWL_WNDPROC, newProc);
+            OS.SetWindowLongPtr (balloonTipHandle_, OS.GWLP_WNDPROC, newProc);
         }
     }
 }
@@ -1698,10 +1879,10 @@
     super.unsubclass ();
     if (ToolTipProc !is null) {
         if (toolTipHandle_ !is null) {
-            OS.SetWindowLong (toolTipHandle_, OS.GWL_WNDPROC, cast(int)ToolTipProc);
+            OS.SetWindowLongPtr (toolTipHandle_, OS.GWLP_WNDPROC, cast(int)ToolTipProc);
         }
         if (toolTipHandle_ !is null) {
-            OS.SetWindowLong (toolTipHandle_, OS.GWL_WNDPROC, cast(int)ToolTipProc);
+            OS.SetWindowLongPtr (toolTipHandle_, OS.GWLP_WNDPROC, cast(int)ToolTipProc);
         }
     }
 }
@@ -1780,7 +1961,7 @@
     static if (OS.IsSP) return cast(int) DialogProc;
     if ((style & DWT.TOOL) !is 0) {
         int trim = DWT.TITLE | DWT.CLOSE | DWT.MIN | DWT.MAX | DWT.BORDER | DWT.RESIZE;
-        if ((style & trim) is 0) super.windowProc ();
+        if ((style & trim) is 0) return super.windowProc ();
     }
     return parent !is null ? cast(int) DialogProc : super.windowProc ();
 }
@@ -1858,14 +2039,14 @@
         * to adding a listener.
         */
         if (hooks (DWT.HardKeyDown) || hooks (DWT.HardKeyUp)) {
-            int fActive = wParam & 0xFFFF;
-            int hwnd = fActive !is 0 ? handle : 0;
+            int fActive = OS.LOWORD (wParam);
+            int /*long*/ hwnd = fActive !is 0 ? handle : 0;
             for (int bVk=OS.VK_APP1; bVk<=OS.VK_APP6; bVk++) {
                 OS.SHSetAppKeyWndAssoc (cast(byte) bVk, hwnd);
             }
         }
         /* Restore SIP state when window is activated */
-        if ((wParam & 0xFFFF) !is 0) {
+        if (OS.LOWORD (wParam) !is 0) {
             OS.SHSipPreference (handle, psai.fSipUp is 0 ? OS.SIP_DOWN : OS.SIP_UP);
         }
     }
@@ -1873,24 +2054,20 @@
     /*
     * Bug in Windows XP.  When a Shell is deactivated, the
     * IME composition window does not go away. This causes
-    * repaint issues.  The fix is to close the IME to cause
-    * the composition string to be committed.
-    *
-    * Note. The IME needs to be reopened in order to preserve
-    * the input method status.
+    * repaint issues.  The fix is to commit the composition
+    * string.
     */
     if (OS.WIN32_VERSION >= OS.VERSION (5, 1)) {
-        if ((wParam & 0xFFFF) is 0 && OS.IsDBLocale && hIMC !is null) {
-            if (OS.ImmGetOpenStatus(hIMC)) {
-                OS.ImmSetOpenStatus (hIMC, false);
-                OS.ImmSetOpenStatus (hIMC, true);
+        if (OS.LOWORD (wParam) is 0 && OS.IsDBLocale && hIMC !is null) {
+            if (OS.ImmGetOpenStatus (hIMC)) {
+                OS.ImmNotifyIME (hIMC, OS.NI_COMPOSITIONSTR, OS.CPS_COMPLETE, 0);
             }
         }
     }
 
     /* Process WM_ACTIVATE */
     LRESULT result = super.WM_ACTIVATE (wParam, lParam);
-    if ((wParam & 0xFFFF) is 0) {
+    if (OS.LOWORD (wParam) is 0) {
         if (lParam is 0 || (cast(HANDLE)lParam !is toolTipHandle_ && cast(HANDLE)lParam !is balloonTipHandle_)) {
             ToolTip tip = getCurrentToolTip ();
             if (tip !is null) tip.setVisible (false);
@@ -1906,7 +2083,7 @@
         * been pressed. lParam is either 0 (PocketPC 2002) or the handle
         * to the Shell (PocketPC).
         */
-        int loWord = wParam & 0xFFFF;
+        int loWord = OS.LOWORD (wParam);
         if (loWord is OS.IDOK && (lParam is 0 || lParam is handle)) {
             OS.PostMessage (handle, OS.WM_CLOSE, 0, 0);
             return LRESULT.ZERO;
@@ -1929,7 +2106,7 @@
                 if (lParam is hwndCB) {
                     return super.WM_COMMAND (wParam, 0);
                 } else {
-                    int hwndChild = OS.GetWindow (hwndCB, OS.GW_CHILD);
+                    int /*long*/ hwndChild = OS.GetWindow (hwndCB, OS.GW_CHILD);
                     if (lParam is hwndChild) return super.WM_COMMAND (wParam, 0);
                 }
             }
@@ -1975,10 +2152,8 @@
 override LRESULT WM_ENTERIDLE (int wParam, int lParam) {
     LRESULT result = super.WM_ENTERIDLE (wParam, lParam);
     if (result !is null) return result;
-    static if (OS.IsWinCE) {
-        if (display.runMessages) {
-            if (display.runAsyncMessages (true)) display.wakeThread ();
-        }
+    if (display.runMessages) {
+        if (display.runAsyncMessages (false)) display.wakeThread ();
     }
     return result;
 }
@@ -2006,7 +2181,7 @@
     * and stop the normal shell activation but allow the mouse
     * down to be delivered.
     */
-    int hittest = cast(short) (lParam & 0xFFFF);
+    int hittest = cast(short) OS.LOWORD (lParam);
     switch (hittest) {
         case OS.HTERROR:
         case OS.HTTRANSPARENT:
@@ -2049,8 +2224,7 @@
     POINT pt;
     if (!OS.GetCursorPos (&pt)) {
         int pos = OS.GetMessagePos ();
-        pt.x = cast(short) (pos & 0xFFFF);
-        pt.y = cast(short) (pos >> 16);
+        OS.POINTSTOPOINT (pt, pos);
     }
     auto hwnd = OS.WindowFromPoint (pt);
     if (hwnd is null) return null;
@@ -2073,8 +2247,9 @@
         }
     }
 
+    int /*long*/ code = callWindowProc (handle, OS.WM_MOUSEACTIVATE, wParam, lParam);
     setActiveControl (control);
-    return null;
+    return new LRESULT (code);
 }
 
 override LRESULT WM_MOVE (int wParam, int lParam) {
@@ -2085,32 +2260,16 @@
     return result;
 }
 
-override LRESULT WM_NCACTIVATE (int wParam, int lParam) {
-    Display display = this.display;
-    LRESULT result = super.WM_NCACTIVATE (wParam, lParam);
-    if (display.isXMouseActive ()) {
-        if (lockToolTipControl !is null) {
-            if (OS.GetAsyncKeyState (OS.VK_LBUTTON) < 0) return result;
-            if (OS.GetAsyncKeyState (OS.VK_MBUTTON) < 0) return result;
-            if (OS.GetAsyncKeyState (OS.VK_RBUTTON) < 0) return result;
-            if (OS.GetAsyncKeyState (OS.VK_XBUTTON1) < 0) return result;
-            if (OS.GetAsyncKeyState (OS.VK_XBUTTON2) < 0) return result;
-            return LRESULT.ZERO;
-        }
-    }
-    return result;
-}
-
 override LRESULT WM_NCHITTEST (int wParam, int lParam) {
     if (!OS.IsWindowEnabled (handle)) return null;
     if (!isEnabled () || !isActive ()) {
         if (!Display.TrimEnabled) return new LRESULT (OS.HTNOWHERE);
-        int hittest = callWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam);
+        int /*long*/ hittest = callWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam);
         if (hittest is OS.HTCLIENT || hittest is OS.HTMENU) hittest = OS.HTBORDER;
         return new LRESULT (hittest);
     }
     if (menuBar !is null && !menuBar.getEnabled ()) {
-        int hittest = callWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam);
+        int /*long*/ hittest = callWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam);
         if (hittest is OS.HTMENU) hittest = OS.HTBORDER;
         return new LRESULT (hittest);
     }
@@ -2133,7 +2292,7 @@
     bool fixActive = OS.IsWin95 && display.lastHittest is OS.HTCAPTION;
     if (fixActive) hwndActive = OS.SetActiveWindow (handle);
     display.lockActiveWindow = true;
-    int code = callWindowProc (handle, OS.WM_NCLBUTTONDOWN, wParam, lParam);
+    int /*long*/ code = callWindowProc (handle, OS.WM_NCLBUTTONDOWN, wParam, lParam);
     display.lockActiveWindow = false;
     if (fixActive) OS.SetActiveWindow (hwndActive);
     Control focusControl = display.lastHittestControl;
@@ -2168,7 +2327,7 @@
     * fix is to detect this case and bring the shell
     * forward.
     */
-    int msg = cast(short) (lParam >> 16);
+    int msg = OS.HIWORD (lParam);
     if (msg is OS.WM_LBUTTONDOWN) {
         if (!Display.TrimEnabled) {
             Shell modalShell = display.getModalShell ();
@@ -2203,15 +2362,14 @@
     * with HTERROR to set the cursor but only when the
     * mouse is in the client area of the shell.
     */
-    int hitTest = cast(short) (lParam & 0xFFFF);
+    int hitTest = cast(short) OS.LOWORD (lParam);
     if (hitTest is OS.HTERROR) {
         if (!getEnabled ()) {
             Control control = display.getControl (cast(HANDLE)wParam);
             if (control is this && cursor !is null) {
                 POINT pt;
                 int pos = OS.GetMessagePos ();
-                pt.x = cast(short) (pos & 0xFFFF);
-                pt.y = cast(short) (pos >> 16);
+                OS.POINTSTOPOINT (pt, pos);
                 OS.ScreenToClient (handle, &pt);
                 RECT rect;
                 OS.GetClientRect (handle, &rect);
--- a/dwt/widgets/Slider.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/Slider.d	Sat May 17 17:34:28 2008 +0200
@@ -669,7 +669,7 @@
             case OS.VK_LEFT:
             case OS.VK_RIGHT: {
                 int key = wParam is OS.VK_LEFT ? OS.VK_RIGHT : OS.VK_LEFT;
-                int code = callWindowProc (handle, OS.WM_KEYDOWN, key, lParam);
+                int /*long*/ code = callWindowProc (handle, OS.WM_KEYDOWN, key, lParam);
                 return new LRESULT (code);
             }
             default:
@@ -752,7 +752,7 @@
 override LRESULT wmScrollChild (int wParam, int lParam) {
 
     /* Do nothing when scrolling is ending */
-    int code = wParam & 0xFFFF;
+    int code = OS.LOWORD (wParam);
     if (code is OS.SB_ENDSCROLL) return null;
 
     /* Move the thumb */
--- a/dwt/widgets/Spinner.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/Spinner.d	Sat May 17 17:34:28 2008 +0200
@@ -32,6 +32,7 @@
 import tango.text.convert.Integer : toString;
 static import tango.text.Text;
 alias tango.text.Text.Text!(char) StringBuffer;
+import tango.util.Convert;
 
 /**
  * Instances of this class are selectable user interface
@@ -86,7 +87,22 @@
             static_this_completed = true;
         }
     }
+    /**
+     * the operating system limit for the number of characters
+     * that the text field in an instance of this class can hold
+     *
+     * @since 3.4
+     */
+    public static int LIMIT;
 
+    /*
+     * These values can be different on different platforms.
+     * Therefore they are not initialized in the declaration
+     * to stop the compiler from inlining.
+     */
+    static this() {
+        LIMIT = OS.IsWinNT ? 0x7FFFFFFF : 0x7FFF;
+    }
 
 /**
  * Constructs a new instance of this class given its parent
@@ -173,7 +189,7 @@
         hInstance,
         null);
     if (hwndText is null) error (DWT.ERROR_NO_HANDLES);
-    OS.SetWindowLong (hwndText, OS.GWL_ID, cast(int) hwndText);
+    OS.SetWindowLongPtr (hwndText, OS.GWLP_ID, cast(LONG_PTR)hwndText);
     int upDownStyle = OS.WS_CHILD | OS.WS_VISIBLE | OS.UDS_AUTOBUDDY;
     if ((style & DWT.WRAP) !is 0) upDownStyle |= OS.UDS_WRAP;
     if ((style & DWT.BORDER) !is 0) {
@@ -196,7 +212,7 @@
     if (hwndUpDown is null) error (DWT.ERROR_NO_HANDLES);
     int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE;
     SetWindowPos (hwndText, hwndUpDown, 0, 0, 0, 0, flags);
-    OS.SetWindowLong (hwndUpDown, OS.GWL_ID, cast(int) hwndUpDown);
+    OS.SetWindowLongPtr (hwndUpDown, OS.GWLP_ID, cast(LONG_PTR)hwndUpDown);
     if (OS.IsDBLocale) {
         auto hIMC = OS.ImmGetContext (handle);
         OS.ImmAssociateContext (hwndText, hIMC);
@@ -365,9 +381,9 @@
     * the single-line text widget in an editable combo
     * box.
     */
-    int margins = OS.SendMessage (hwndText, OS.EM_GETMARGINS, 0, 0);
-    x -= margins & 0xFFFF;
-    width += (margins & 0xFFFF) + ((margins >> 16) & 0xFFFF);
+    int /*long*/ margins = OS.SendMessage (hwndText, OS.EM_GETMARGINS, 0, 0);
+    x -= OS.LOWORD (margins);
+    width += OS.LOWORD (margins) + OS.HIWORD (margins);
     if ((style & DWT.BORDER) !is 0) {
         x -= 1;
         y -= 1;
@@ -538,13 +554,13 @@
 public int getSelection () {
     checkWidget ();
     static if (OS.IsWinCE) {
-        return OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0) & 0xFFFF;
+        return OS.LOWORD (OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0));
     } else {
         return OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0);
     }
 }
 
-int getSelectionText () {
+int getSelectionText (bool [] parseFail) {
     int length_ = OS.GetWindowTextLength (hwndText);
     TCHAR[] buffer = NewTCHARs (getCodePage (), length_ + 1);
     OS.GetWindowText (hwndText, buffer.ptr, length_ + 1);
@@ -555,7 +571,8 @@
             String decimalSeparator = getDecimalSeparator ();
             int index = string.indexOf (decimalSeparator);
             if (index !is -1)  {
-                String wholePart = string.substring (0, index);
+                int startIndex = string.startsWith ("+") || string.startsWith ("-") ? 1 : 0;
+                String wholePart = startIndex !is index ? string.substring (startIndex, index) : "0";
                 String decimalPart = string.substring (index + 1);
                 if (decimalPart.length > digits) {
                     decimalPart = decimalPart.substring (0, digits);
@@ -569,8 +586,10 @@
                 int decimalValue = Integer.parseInt (decimalPart);
                 for (int i = 0; i < digits; i++) wholeValue *= 10;
                 value = wholeValue + decimalValue;
+                if (string.startsWith ("-")) value = -value;
             } else {
                 value = Integer.parseInt (string);
+                for (int i = 0; i < digits; i++) value *= 10;
             }
         } else {
             value = Integer.parseInt (string);
@@ -580,9 +599,55 @@
         if (min <= value && value <= max) return value;
     } catch (NumberFormatException e) {
     }
+    parseFail [0] = true;
     return -1;
 }
 
+/**
+ * Returns a string containing a copy of the contents of the
+ * receiver's text field, or an empty string if there are no
+ * contents.
+ *
+ * @return the receiver's text
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @since 3.4
+ */
+public String getText () {
+    checkWidget ();
+    int length_ = OS.GetWindowTextLength (hwndText);
+    if (length_ is 0) return "";
+    TCHAR[] buffer = NewTCHARs (getCodePage (), length_ + 1);
+    OS.GetWindowText (hwndText, buffer.ptr, length_ + 1);
+    return TCHARsToStr( buffer[0 .. length_] );
+}
+
+/**
+ * Returns the maximum number of characters that the receiver's
+ * text field is capable of holding. If this has not been changed
+ * by <code>setTextLimit()</code>, it will be the constant
+ * <code>Spinner.LIMIT</code>.
+ *
+ * @return the text limit
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @see #LIMIT
+ *
+ * @since 3.4
+ */
+public int getTextLimit () {
+    checkWidget ();
+    return OS.SendMessage (hwndText, OS.EM_GETLIMITTEXT, 0, 0) & 0x7FFFFFFF;
+}
+
 int mbcsToWcsPos (int mbcsPos) {
     if (mbcsPos <= 0) return 0;
     if (OS.IsUnicode) return mbcsPos;
@@ -817,7 +882,7 @@
     this.digits = value;
     int pos;
     static if (OS.IsWinCE) {
-        pos = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0) & 0xFFFF;
+        pos = OS.LOWORD (OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0));
     } else {
         pos = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0);
     }
@@ -876,13 +941,12 @@
  */
 public void setMaximum (int value) {
     checkWidget ();
-    if (value < 0) return;
     int min;
     OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, &min, null);
     if (value <= min) return;
     int pos;
     static if (OS.IsWinCE) {
-        pos = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0) & 0xFFFF;
+        pos = OS.LOWORD (OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0));
     } else {
         pos = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0);
     }
@@ -892,11 +956,11 @@
 
 /**
  * Sets the minimum value that the receiver will allow.  This new
- * value will be ignored if it is negative or is not less than the receiver's
+ * value will be ignored if it is not less than the receiver's
  * current maximum value.  If the new minimum is applied then the receiver's
  * selection value will be adjusted if necessary to fall within its new range.
  *
- * @param value the new minimum, which must be nonnegative and less than the current maximum
+ * @param value the new minimum, which must be less than the current maximum
  *
  * @exception DWTException <ul>
  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
@@ -905,13 +969,12 @@
  */
 public void setMinimum (int value) {
     checkWidget ();
-    if (value < 0) return;
     int max;
     OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, null, &max);
     if (value >= max) return;
     int pos;
     static if (OS.IsWinCE) {
-        pos = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0) & 0xFFFF;
+        pos = OS.LOWORD (OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0));
     } else {
         pos = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0);
     }
@@ -963,11 +1026,15 @@
         OS.SendMessage (hwndUpDown , OS.IsWinCE ? OS.UDM_SETPOS : OS.UDM_SETPOS32, 0, value);
     }
     if (setText) {
-        String string = .toString( value );
-        if (digits > 0) {
+        String string;
+        if (digits is 0) {
+            string = .toString (value);
+        } else {
+            string = to!(String)(Math.abs (value));
             String decimalSeparator = getDecimalSeparator ();
             int index = string.length - digits;
             StringBuffer buffer = new StringBuffer ();
+            if (value < 0) buffer.append ("-");
             if (index > 0) {
                 buffer.append (string.substring (0, index));
                 buffer.append (decimalSeparator);
@@ -987,10 +1054,42 @@
         }
         TCHAR* buffer = StrToTCHARz (getCodePage (), string);
         OS.SetWindowText (hwndText, buffer);
+        OS.SendMessage (hwndText, OS.EM_SETSEL, 0, -1);
+        if (!OS.IsWinCE) {
+            OS.NotifyWinEvent (OS.EVENT_OBJECT_FOCUS, hwndText, OS.OBJID_CLIENT, 0);
+        }
     }
     if (notify) postEvent (DWT.Selection);
 }
 
+/**
+ * Sets the maximum number of characters that the receiver's
+ * text field is capable of holding to be the argument.
+ * <p>
+ * To reset this value to the default, use <code>setTextLimit(Spinner.LIMIT)</code>.
+ * Specifying a limit value larger than <code>Spinner.LIMIT</code> sets the
+ * receiver's limit to <code>Spinner.LIMIT</code>.
+ * </p>
+ * @param limit new text limit
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_CANNOT_BE_ZERO - if the limit is zero</li>
+ * </ul>
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @see #LIMIT
+ *
+ * @since 3.4
+ */
+public void setTextLimit (int limit) {
+    checkWidget ();
+    if (limit is 0) error (DWT.ERROR_CANNOT_BE_ZERO);
+    OS.SendMessage (hwndText, OS.EM_SETLIMITTEXT, limit, 0);
+}
+
 override void setToolTipText (Shell shell, String string) {
     shell.setToolTipText (hwndText, string);
     shell.setToolTipText (hwndUpDown, string);
@@ -1021,7 +1120,6 @@
  */
 public void setValues (int selection, int minimum, int maximum, int digits, int increment, int pageIncrement) {
     checkWidget ();
-    if (minimum < 0) return;
     if (maximum <= minimum) return;
     if (digits < 0) return;
     if (increment < 1) return;
@@ -1036,15 +1134,15 @@
 
 override void subclass () {
     super.subclass ();
-    int newProc = display.windowProc;
-    OS.SetWindowLong (hwndText, OS.GWL_WNDPROC, newProc);
-    OS.SetWindowLong (hwndUpDown, OS.GWL_WNDPROC, newProc);
+    int /*long*/ newProc = display.windowProc;
+    OS.SetWindowLongPtr (hwndText, OS.GWLP_WNDPROC, newProc);
+    OS.SetWindowLongPtr (hwndUpDown, OS.GWLP_WNDPROC, newProc);
 }
 
 override void unsubclass () {
     super.unsubclass ();
-    OS.SetWindowLong (hwndText, OS.GWL_WNDPROC, cast(int) EditProc);
-    OS.SetWindowLong (hwndUpDown, OS.GWL_WNDPROC, cast(int) UpDownProc);
+    OS.SetWindowLongPtr (hwndText, OS.GWLP_WNDPROC, cast(LONG_PTR)EditProc);
+    OS.SetWindowLongPtr (hwndUpDown, OS.GWLP_WNDPROC, cast(LONG_PTR)UpDownProc);
 }
 
 String verifyText (String string, int start, int end, Event keyEvent) {
@@ -1066,6 +1164,11 @@
         }
         index = 0;
     }
+    if (string.length > 0) {
+        int min;
+        OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, &min, null);
+        if (min < 0 && string.charAt (0) is '-') index++;
+    }
     while (index < string.length ) {
         if (!CharacterIsDigit (string.charAt (index))) break;
         index++;
@@ -1157,6 +1260,7 @@
 
 override LRESULT WM_SETFOCUS (int wParam, int lParam) {
     OS.SetFocus (hwndText);
+    OS.SendMessage (hwndText, OS.EM_SETSEL, 0, -1);
     return null;
 }
 
@@ -1170,7 +1274,7 @@
 override LRESULT WM_SIZE (int wParam, int lParam) {
     LRESULT result = super.WM_SIZE (wParam, lParam);
     if (isDisposed ()) return result;
-    int width = lParam & 0xFFFF, height = lParam >> 16;
+    int width = OS.LOWORD (lParam), height = OS.HIWORD (lParam);
     int upDownWidth = OS.GetSystemMetrics (OS.SM_CXVSCROLL);
     int textWidth = width - upDownWidth;
     int border = OS.GetSystemMetrics (OS.SM_CXEDGE);
@@ -1269,15 +1373,16 @@
 }
 
 override LRESULT wmCommandChild (int wParam, int lParam) {
-    int code = wParam >> 16;
+    int code = OS.HIWORD (wParam);
     switch (code) {
         case OS.EN_CHANGE:
             if (ignoreModify) break;
-            int value = getSelectionText ();
-            if (value !is -1) {
+            bool [] parseFail = new bool [1];
+            int value = getSelectionText (parseFail);
+            if (!parseFail [0]) {
                 int pos;
                 static if (OS.IsWinCE) {
-                    pos = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0) & 0xFFFF;
+                    pos = OS.LOWORD (OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0));
                 } else {
                     pos = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0);
                 }
@@ -1307,10 +1412,11 @@
         default:
     }
     if (delta !is 0) {
-        int value = getSelectionText ();
-        if (value !is -1) {
+        bool [1] parseFail;
+        int value = getSelectionText (parseFail);
+        if (parseFail [0]) {
             static if (OS.IsWinCE) {
-                value = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0) & 0xFFFF;
+                value = OS.LOWORD (OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0));
             } else {
                 value = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0);
             }
@@ -1337,10 +1443,11 @@
 }
 
 override LRESULT wmKillFocus (HWND hwnd, int wParam, int lParam) {
-    int value = getSelectionText ();
-    if (value is -1) {
+    bool [1] parseFail;
+    int value = getSelectionText (parseFail);
+    if (parseFail [0]) {
         static if (OS.IsWinCE) {
-            value = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0) & 0xFFFF;
+            value = OS.LOWORD (OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0));
         } else {
             value = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0);
         }
@@ -1380,7 +1487,7 @@
 }
 
 override LRESULT wmScrollChild (int wParam, int lParam) {
-    int code = wParam & 0xFFFF;
+    int code = OS.LOWORD (wParam);
     switch (code) {
         case OS.SB_THUMBPOSITION:
             postEvent (DWT.Selection);
--- a/dwt/widgets/Synchronizer.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/Synchronizer.d	Sat May 17 17:34:28 2008 +0200
@@ -20,6 +20,7 @@
 
 import dwt.DWT;
 import tango.core.Thread;
+import dwt.graphics.Device;
 import tango.core.Exception;
 
 /**
@@ -45,6 +46,8 @@
     RunnableLock [] messages;
     Object messageLock;
     Thread syncThread;
+    static final int GROW_SIZE = 4;
+    static final int MESSAGE_LIMIT = 64;
 
     //TEMPORARY CODE
     static final bool IS_CARBON = false;//"carbon".equals (DWT.getPlatform ());
@@ -62,9 +65,9 @@
 void addLast (RunnableLock lock) {
     bool wake = false;
     synchronized (messageLock) {
-        if (messages is null) messages = new RunnableLock [4];
+        if (messages is null) messages = new RunnableLock [GROW_SIZE];
         if (messageCount is messages.length) {
-            RunnableLock[] newMessages = new RunnableLock [messageCount + 4];
+            RunnableLock[] newMessages = new RunnableLock [messageCount + GROW_SIZE];
             System.arraycopy (messages, 0, newMessages, 0, messageCount);
             messages = newMessages;
         }
@@ -116,7 +119,7 @@
         System.arraycopy (messages, 1, messages, 0, --messageCount);
         messages [messageCount] = null;
         if (messageCount is 0) {
-            if (messages.length > 64) messages = null;
+            if (messages.length > MESSAGE_LIMIT) messages = null;
         }
         return lock;
     }
@@ -163,21 +166,27 @@
  * @see #asyncExec
  */
 public void syncExec (Runnable runnable) {
-    if (display.isValidThread ()) {
+    RunnableLock lock = null;
+    synchronized (Device.classinfo) {
+        if (display is null || display.isDisposed ()) DWT.error (DWT.ERROR_DEVICE_DISPOSED);
+        if (!display.isValidThread ()) {
+            if (runnable is null) {
+                display.wake ();
+                return;
+            }
+            lock = new RunnableLock (runnable);
+            /*
+             * Only remember the syncThread for syncExec.
+             */
+            lock.thread = Thread.getThis();
+            addLast (lock);
+        }
+    }
+    if (lock is null) {
         if (runnable !is null) runnable.run ();
         return;
     }
-    if (runnable is null) {
-        display.wake ();
-        return;
-    }
-    RunnableLock lock = new RunnableLock (runnable);
-    /*
-     * Only remember the syncThread for syncExec.
-     */
-    lock.thread = Thread.getThis();
     synchronized (lock) {
-        addLast (lock);
         bool interrupted = false;
         while (!lock.done ()) {
             try {
--- a/dwt/widgets/TabFolder.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/TabFolder.d	Sat May 17 17:34:28 2008 +0200
@@ -376,6 +376,35 @@
 }
 
 /**
+ * Returns the tab item at the given point in the receiver
+ * or null if no such item exists. The point is in the
+ * coordinate system of the receiver.
+ *
+ * @param point the point used to locate the item
+ * @return the tab item at the given point, or null if the point is not in a tab item
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the point is null</li>
+ * </ul>
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @since 3.4
+ */
+public TabItem getItem (Point point) {
+    checkWidget ();
+    if (point is null) error (DWT.ERROR_NULL_ARGUMENT);
+    TCHITTESTINFO pinfo;
+    pinfo.pt.x = point.x;
+    pinfo.pt.y = point.y;
+    int index = OS.SendMessage (handle, OS.TCM_HITTEST, 0, &pinfo);
+    if (index is -1) return null;
+    return items [index];
+}
+
+/**
  * Returns the number of items contained in the receiver.
  *
  * @return the number of items
@@ -732,6 +761,18 @@
     int index = hdr.hdr.idFrom;
     auto hwndToolTip = cast(HWND) OS.SendMessage (handle, OS.TCM_GETTOOLTIPS, 0, 0);
     if (hwndToolTip is hdr.hdr.hwndFrom) {
+        /*
+        * Bug in Windows. For some reason the reading order
+        * in NMTTDISPINFO is sometimes set incorrectly.  The
+        * reading order seems to change every time the mouse
+        * enters the control from the top edge.  The fix is
+        * to explicitly set TTF_RTLREADING.
+        */
+        if ((style & DWT.RIGHT_TO_LEFT) !is 0) {
+            hdr.uFlags |= OS.TTF_RTLREADING;
+        } else {
+            hdr.uFlags &= ~OS.TTF_RTLREADING;
+        }
         if (toolTipText_ !is null) return "";
         if (0 <= index && index < items.length) {
             TabItem item = items [index];
@@ -835,7 +876,7 @@
     * default window proc that returns HTCLIENT when
     * the mouse is in the client area.
     */
-    int hittest = OS.DefWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam);
+    int /*long*/ hittest = OS.DefWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam);
     return new LRESULT (hittest);
 }
 
@@ -878,10 +919,10 @@
     */
     if (OS.WIN32_VERSION < OS.VERSION (4, 10)) return result;
     if ((style & DWT.RIGHT_TO_LEFT) !is 0) {
-        int code = wParam & 0xFFFF;
+        int code = OS.LOWORD (wParam);
         switch (code) {
             case OS.WM_CREATE: {
-                int id = (wParam >> 16);
+                int id = OS.HIWORD (wParam);
                 HWND hwnd = cast(HWND) lParam;
                 if (id is ID_UPDOWN) {
                     auto bits = OS.GetWindowLong (hwnd, OS.GWL_EXSTYLE);
--- a/dwt/widgets/TabItem.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/TabItem.d	Sat May 17 17:34:28 2008 +0200
@@ -15,6 +15,7 @@
 import dwt.DWT;
 import dwt.DWTException;
 import dwt.graphics.Image;
+import dwt.graphics.Rectangle;
 import dwt.internal.win32.OS;
 
 import dwt.widgets.Item;
@@ -177,6 +178,28 @@
 }
 
 /**
+ * Returns a rectangle describing the receiver's size and location
+ * relative to its parent.
+ *
+ * @return the receiver's bounding rectangle
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @since 3.4
+ */
+public Rectangle getBounds() {
+    checkWidget();
+    int index = parent.indexOf(this);
+    if (index is -1) return new Rectangle (0, 0, 0, 0);
+    RECT itemRect;
+    OS.SendMessage (parent.handle, OS.TCM_GETITEMRECT, index, &itemRect);
+    return new Rectangle(itemRect.left, itemRect.top, itemRect.right - itemRect.left, itemRect.bottom - itemRect.top);
+}
+
+/**
  * Returns the receiver's parent, which must be a <code>TabFolder</code>.
  *
  * @return the receiver's parent
--- a/dwt/widgets/Table.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/Table.d	Sat May 17 17:34:28 2008 +0200
@@ -33,6 +33,7 @@
 import dwt.widgets.Event;
 import dwt.widgets.Control;
 import dwt.widgets.Display;
+import dwt.widgets.Shell;
 
 import dwt.dwthelper.utils;
 
@@ -66,12 +67,13 @@
  * </pre></code>
  * </p><p>
  * Note that although this class is a subclass of <code>Composite</code>,
- * it does not make sense to add <code>Control</code> children to it,
- * or set a layout on it.
+ * it does not normally make sense to add <code>Control</code> children to
+ * it, or set a layout on it, unless implementing something like a cell
+ * editor.
  * </p><p>
  * <dl>
  * <dt><b>Styles:</b></dt>
- * <dd>SINGLE, MULTI, CHECK, FULL_SELECTION, HIDE_SELECTION, VIRTUAL</dd>
+ * <dd>SINGLE, MULTI, CHECK, FULL_SELECTION, HIDE_SELECTION, VIRTUAL, NO_SCROLL</dd>
  * <dt><b>Events:</b></dt>
  * <dd>Selection, DefaultSelection, SetData, MeasureItem, EraseItem, PaintItem</dd>
  * </dl>
@@ -96,10 +98,11 @@
     ImageList imageList, headerImageList;
     TableItem currentItem;
     TableColumn sortColumn;
+    RECT* focusRect;
+    HWND headerToolTipHandle;
     bool ignoreCustomDraw, ignoreDrawForeground, ignoreDrawBackground, ignoreDrawFocus, ignoreDrawSelection, ignoreDrawHot;
     bool customDraw, dragStarted, explorerTheme, firstColumnImage, fixScrollWidth, tipRequested, wasSelected, wasResized;
-    bool ignoreActivate, ignoreSelect, ignoreShrink, ignoreResize, ignoreColumnMove, ignoreColumnResize;
-    HWND headerToolTipHandle;
+    bool ignoreActivate, ignoreSelect, ignoreShrink, ignoreResize, ignoreColumnMove, ignoreColumnResize, fullRowSelect;
     int itemHeight, lastIndexOf, lastWidth, sortDirection, resizeCount, selectionForeground, hotIndex;
     static /*final*/ WNDPROC HeaderProc;
     static const int INSET = 4;
@@ -109,6 +112,8 @@
     static const int HEADER_EXTRA = 3;
     static const int VISTA_EXTRA = 2;
     static const int EXPLORER_EXTRA = 2;
+    static final int H_SCROLL_LIMIT = 32;
+    static final int V_SCROLL_LIMIT = 16;
     static const bool EXPLORER_THEME = true;
     private static /+const+/ WNDPROC TableProc;
     static const TCHAR[] TableClass = OS.WC_LISTVIEW;
@@ -159,6 +164,7 @@
  * @see DWT#FULL_SELECTION
  * @see DWT#HIDE_SELECTION
  * @see DWT#VIRTUAL
+ * @see DWT#NO_SCROLL
  * @see Widget#checkSubclass
  * @see Widget#getStyle
  */
@@ -176,8 +182,7 @@
             setCustomDraw (true);
             setBackgroundTransparent (true);
             if (OS.COMCTL32_MAJOR < 6) style |= DWT.DOUBLE_BUFFERED;
-            //TODO - LVS_EX_LABELTIP causes white rectangles (turn it off)
-            OS.SendMessage (handle, OS.LVM_SETEXTENDEDLISTVIEWSTYLE, OS.LVS_EX_LABELTIP, 0);
+            if (OS.IsWinCE) OS.SendMessage (handle, OS.LVM_SETEXTENDEDLISTVIEWSTYLE, OS.LVS_EX_LABELTIP, 0);
             break;
         default:
     }
@@ -263,7 +268,16 @@
         /* Resize messages */
         case OS.WM_WINDOWPOSCHANGED:
             redraw = findImageControl () !is null && drawCount is 0 && OS.IsWindowVisible (handle);
-            if (redraw) OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+            if (redraw) {
+                /*
+                * Feature in Windows.  When LVM_SETBKCOLOR is used with CLR_NONE
+                * to make the background of the table transparent, drawing becomes
+                * slow.  The fix is to temporarily clear CLR_NONE when redraw is
+                * turned off.
+                */
+                OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+                OS.SendMessage (handle, OS.LVM_SETBKCOLOR, 0, 0xFFFFFF);
+            }
             //FALL THROUGH
 
         /* Mouse messages */
@@ -298,7 +312,66 @@
     bool oldSelected = wasSelected;
     if (checkSelection) wasSelected = false;
     if (checkActivate) ignoreActivate = true;
-    int code = OS.CallWindowProc (TableProc, hwnd, msg, wParam, lParam);
+
+    /*
+    * Bug in Windows.  For some reason, when the WS_EX_COMPOSITED
+    * style is set in a parent of a table and the header is visible,
+    * Windows issues an endless stream of WM_PAINT messages.  The
+    * fix is to call BeginPaint() and EndPaint() outside of WM_PAINT
+    * and pass the paint HDC in to the window proc.
+    */
+    bool fixPaint = false;
+    if (msg is OS.WM_PAINT) {
+        int bits0 = OS.GetWindowLong (handle, OS.GWL_STYLE);
+        if ((bits0 & OS.LVS_NOCOLUMNHEADER) is 0) {
+            HWND hwndParent = OS.GetParent (handle), hwndOwner = null;
+            while (hwndParent !is null) {
+                int bits1 = OS.GetWindowLong (hwndParent, OS.GWL_EXSTYLE);
+                if ((bits1 & OS.WS_EX_COMPOSITED) !is 0) {
+                    fixPaint = true;
+                    break;
+                }
+                hwndOwner = OS.GetWindow (hwndParent, OS.GW_OWNER);
+                if (hwndOwner !is null) break;
+                hwndParent = OS.GetParent (hwndParent);
+            }
+        }
+    }
+
+    /* Remove the scroll bars that Windows keeps automatically adding */
+    bool fixScroll = false;
+    if ((style & DWT.H_SCROLL) is 0 || (style & DWT.V_SCROLL) is 0) {
+        switch (msg) {
+            case OS.WM_PAINT:
+            case OS.WM_NCPAINT:
+            case OS.WM_WINDOWPOSCHANGING: {
+                int bits = OS.GetWindowLong (hwnd, OS.GWL_STYLE);
+                if ((style & DWT.H_SCROLL) is 0 && (bits & OS.WS_HSCROLL) !is 0) {
+                    fixScroll = true;
+                    bits &= ~OS.WS_HSCROLL;
+                }
+                if ((style & DWT.V_SCROLL) is 0 && (bits & OS.WS_VSCROLL) !is 0) {
+                    fixScroll = true;
+                    bits &= ~OS.WS_VSCROLL;
+                }
+                if (fixScroll) OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+            }
+        }
+    }
+    int /*long*/ code = 0;
+    if (fixPaint) {
+        PAINTSTRUCT ps;
+        auto hDC = OS.BeginPaint (hwnd, &ps);
+        code = TableProc( hwnd, OS.WM_PAINT, cast(int)hDC, lParam);
+        OS.EndPaint (hwnd, &ps);
+    } else {
+        code = TableProc( hwnd, msg, wParam, lParam);
+    }
+    if (fixScroll) {
+        int flags = OS.RDW_FRAME | OS.RDW_INVALIDATE;
+        OS.RedrawWindow (handle, null, null, flags);
+    }
+
     if (checkActivate) ignoreActivate = false;
     if (checkSelection) {
         if (wasSelected || forceSelect) {
@@ -328,6 +401,7 @@
         /* Resize messages */
         case OS.WM_WINDOWPOSCHANGED:
             if (redraw) {
+                OS.SendMessage (handle, OS.LVM_SETBKCOLOR, 0, OS.CLR_NONE);
                 OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
                 OS.InvalidateRect (handle, null, true);
                 auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
@@ -370,13 +444,17 @@
 
 static int checkStyle (int style) {
     /*
-    * Feature in Windows.  It is not possible to create
-    * a table that does not have scroll bars.  Therefore,
-    * no matter what style bits are specified, set the
-    * H_SCROLL and V_SCROLL bits so that the DWT style
-    * will match the widget that Windows creates.
+    * Feature in Windows.  Even when WS_HSCROLL or
+    * WS_VSCROLL is not specified, Windows creates
+    * trees and tables with scroll bars.  The fix
+    * is to set H_SCROLL and V_SCROLL.
+    *
+    * NOTE: This code appears on all platforms so that
+    * applications have consistent scroll bar behavior.
     */
-    style |= DWT.H_SCROLL | DWT.V_SCROLL;
+    if ((style & DWT.NO_SCROLL) is 0) {
+        style |= DWT.H_SCROLL | DWT.V_SCROLL;
+    }
     return checkBits (style, DWT.SINGLE, DWT.MULTI, 0, 0, 0, 0);
 }
 
@@ -497,6 +575,13 @@
                 int dwExStyle = OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
                 if ((dwExStyle & OS.LVS_EX_FULLROWSELECT) is 0) {
                     int bits = OS.LVS_EX_FULLROWSELECT;
+                    /*
+                    * Feature in Windows.  When LVM_SETEXTENDEDLISTVIEWSTYLE is
+                    * used to set or clear the extended style bits and the table
+                    * has a tooltip, the tooltip is hidden.  The fix is to clear
+                    * the tooltip before setting the bits and then reset it.
+                    */
+                    int /*long*/ hwndToolTip = OS.SendMessage (handle, OS.LVM_SETTOOLTIPS, 0, 0);
                     static if (OS.IsWinCE) {
                         RECT rect;
                         bool damaged = cast(bool) OS.GetUpdateRect (handle, &rect, true);
@@ -511,6 +596,12 @@
                         if (result !is OS.NULLREGION) OS.InvalidateRgn (handle, rgn, true);
                         OS.DeleteObject (rgn);
                     }
+                    /*
+                    * Bug in Windows.  Despite the documentation, LVM_SETTOOLTIPS
+                    * uses WPARAM instead of LPARAM for the new tooltip  The fix
+                    * is to put the tooltip in both parameters.
+                    */
+                    hwndToolTip = OS.SendMessage (handle, OS.LVM_SETTOOLTIPS, hwndToolTip, hwndToolTip);
                 }
             }
         }
@@ -536,6 +627,13 @@
                 int dwExStyle = OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
                 if ((dwExStyle & OS.LVS_EX_FULLROWSELECT) !is 0) {
                     int bits = OS.LVS_EX_FULLROWSELECT;
+                    /*
+                    * Feature in Windows.  When LVM_SETEXTENDEDLISTVIEWSTYLE is
+                    * used to set or clear the extended style bits and the table
+                    * has a tooltip, the tooltip is hidden.  The fix is to clear
+                    * the tooltip before setting the bits and then reset it.
+                    */
+                    auto hwndToolTip = OS.SendMessage (handle, OS.LVM_SETTOOLTIPS, 0, 0);
                     static if (OS.IsWinCE) {
                         RECT rect;
                         bool damaged = cast(bool) OS.GetUpdateRect (handle, &rect, true);
@@ -550,6 +648,12 @@
                         if (result !is OS.NULLREGION) OS.InvalidateRgn (handle, rgn, true);
                         OS.DeleteObject (rgn);
                     }
+                    /*
+                    * Bug in Windows.  Despite the documentation, LVM_SETTOOLTIPS
+                    * uses WPARAM instead of LPARAM for the new tooltip  The fix
+                    * is to put the tooltip in both parameters.
+                    */
+                    hwndToolTip = OS.SendMessage (handle, OS.LVM_SETTOOLTIPS, hwndToolTip, hwndToolTip);
                 }
             }
         }
@@ -653,6 +757,12 @@
             sendPaintItemEvent (item, nmcd);
             //widget could be disposed at this point
         }
+        if (!ignoreDrawFocus && focusRect !is null) {
+            OS.SetTextColor (nmcd.nmcd.hdc, 0);
+            OS.SetBkColor (nmcd.nmcd.hdc, 0xFFFFFF);
+            OS.DrawFocusRect (nmcd.nmcd.hdc, focusRect);
+            focusRect = null;
+        }
     }
     return null;
 }
@@ -672,8 +782,7 @@
     */
     TableItem item = _getItem (nmcd.nmcd.dwItemSpec);
     if (item is null) return null;
-    HFONT hFont = item.cellFont !is null ? item.cellFont [nmcd.iSubItem] : cast(HFONT)-1;
-    if (hFont is cast(HFONT)-1) hFont = item.font;
+    HFONT hFont = item.fontHandle (nmcd.iSubItem);
     if (hFont !is cast(HFONT)-1) OS.SelectObject (hDC, hFont);
     if (ignoreCustomDraw || (nmcd.nmcd.rc.left is nmcd.nmcd.rc.right)) {
         return new LRESULT (hFont is cast(HFONT)-1 ? OS.CDRF_DODEFAULT : OS.CDRF_NEWFONT);
@@ -682,12 +791,13 @@
     selectionForeground = -1;
     ignoreDrawForeground = ignoreDrawSelection = ignoreDrawFocus = ignoreDrawBackground = false;
     if (OS.IsWindowVisible (handle)) {
+        Event measureEvent = null;
         if (hooks (DWT.MeasureItem)) {
-            sendMeasureItemEvent (item, nmcd.nmcd.dwItemSpec, nmcd.iSubItem, nmcd.nmcd.hdc);
+            measureEvent = sendMeasureItemEvent (item, nmcd.nmcd.dwItemSpec, nmcd.iSubItem, nmcd.nmcd.hdc);
             if (isDisposed () || item.isDisposed ()) return null;
         }
         if (hooks (DWT.EraseItem)) {
-            sendEraseItemEvent (item, nmcd, lParam);
+            sendEraseItemEvent (item, nmcd, lParam, measureEvent);
             if (isDisposed () || item.isDisposed ()) return null;
             code |= OS.CDRF_NOTIFYPOSTPAINT;
         }
@@ -723,7 +833,7 @@
                 if ((result !is 0 && (lvItem.state & OS.LVIS_SELECTED) !is 0)) {
                     int clrSelection = -1;
                     if (nmcd.iSubItem is 0) {
-                        if (OS.GetFocus () is handle) {
+                        if (OS.GetFocus () is handle || display.getHighContrast ()) {
                             clrSelection = OS.GetSysColor (OS.COLOR_HIGHLIGHT);
                         } else {
                             if ((style & DWT.HIDE_SELECTION) is 0) {
@@ -731,7 +841,7 @@
                             }
                         }
                     } else {
-                        if (OS.GetFocus () is handle) {
+                        if (OS.GetFocus () is handle || display.getHighContrast ()) {
                             clrText = OS.GetSysColor (OS.COLOR_HIGHLIGHTTEXT);
                             clrTextBk = clrSelection = OS.GetSysColor (OS.COLOR_HIGHLIGHT);
                         } else {
@@ -1172,11 +1282,11 @@
         }
         bits |= width & 0xFFFF;
     }
-    int result = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, -1, bits | 0xFFFF0000);
-    int width = result & 0xFFFF;
-    int empty = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 0, 0);
-    int oneItem = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 1, 0);
-    int itemHeight = (oneItem >> 16) - (empty >> 16);
+    int /*long*/ result = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, -1, OS.MAKELPARAM (bits, 0xFFFF));
+    int width = OS.LOWORD (result);
+    int /*long*/ empty = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 0, 0);
+    int /*long*/ oneItem = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 1, 0);
+    int itemHeight = OS.HIWORD (oneItem) - OS.HIWORD (empty);
     height += OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0) * itemHeight;
     if (width is 0) width = DEFAULT_WIDTH;
     if (height is 0) height = DEFAULT_HEIGHT;
@@ -1199,7 +1309,7 @@
 
     /* Use the Explorer theme */
     if (EXPLORER_THEME) {
-        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0) && OS.IsAppThemed ()) {
             explorerTheme = true;
             OS.SetWindowTheme (handle, Display.EXPLORER.ptr, null);
         }
@@ -1208,7 +1318,7 @@
     /* Get the header window proc */
     if (HeaderProc is null) {
         auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
-        HeaderProc = cast(WNDPROC) OS.GetWindowLong (hwndHeader, OS.GWL_WNDPROC);
+        HeaderProc = cast(WNDPROC) OS.GetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC);
     }
 
     /*
@@ -1237,9 +1347,9 @@
 
     /* Set the checkbox image list */
     if ((style & DWT.CHECK) !is 0) {
-        int empty = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 0, 0);
-        int oneItem = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 1, 0);
-        int width = (oneItem >> 16) - (empty >> 16), height = width;
+        int /*long*/ empty = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 0, 0);
+        int /*long*/ oneItem = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 1, 0);
+        int width = OS.HIWORD (oneItem) - OS.HIWORD (empty), height = width;
         setCheckboxImageList (width, height, false);
         OS.SendMessage (handle, OS. LVM_SETCALLBACKMASK, OS.LVIS_STATEIMAGEMASK, 0);
     }
@@ -1290,22 +1400,30 @@
     *
     * NOTE: WS_EX_LAYOUTRTL is not supported on Windows NT.
     */
-    if (OS.WIN32_VERSION < OS.VERSION (4, 10)) return;
-    if ((style & DWT.RIGHT_TO_LEFT) !is 0) {
-        auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
-        int bits2 = OS.GetWindowLong (hwndHeader, OS.GWL_EXSTYLE);
-        OS.SetWindowLong (hwndHeader, OS.GWL_EXSTYLE, bits2 | OS.WS_EX_LAYOUTRTL);
+    if (OS.WIN32_VERSION >= OS.VERSION (4, 10)) {
+        if ((style & DWT.RIGHT_TO_LEFT) !is 0) {
+            auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+            int bits2 = OS.GetWindowLong (hwndHeader, OS.GWL_EXSTYLE);
+            OS.SetWindowLong (hwndHeader, OS.GWL_EXSTYLE, bits2 | OS.WS_EX_LAYOUTRTL);
+            auto hwndTooltop = cast(HWND)OS.SendMessage (handle, OS.LVM_GETTOOLTIPS, 0, 0);
+            int bits3 = OS.GetWindowLong (hwndTooltop, OS.GWL_EXSTYLE);
+            OS.SetWindowLong (hwndTooltop, OS.GWL_EXSTYLE, bits3 | OS.WS_EX_LAYOUTRTL);
+        }
     }
 }
 
 void createHeaderToolTips () {
     static if (OS.IsWinCE) return;
     if (headerToolTipHandle !is null) return;
+    int bits = 0;
+    if (OS.WIN32_VERSION >= OS.VERSION (4, 10)) {
+        if ((style & DWT.RIGHT_TO_LEFT) !is 0) bits |= OS.WS_EX_LAYOUTRTL;
+    }
     headerToolTipHandle = OS.CreateWindowEx (
-        0,
+        bits,
         OS.TOOLTIPS_CLASS.ptr,
         null,
-        0,
+        OS.TTS_NOPREFIX,
         OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
         handle,
         null,
@@ -1382,11 +1500,10 @@
                 item.cellForeground = temp;
             }
             if (item.cellFont !is null) {
-                auto cellFont = item.cellFont;
-                HFONT[] temp = new HFONT[]( columnCount + 1 );
+                Font [] cellFont = item.cellFont;
+                Font [] temp = new Font [columnCount + 1];
                 System.arraycopy (cellFont, 0, temp, 0, index);
                 System.arraycopy (cellFont, index, temp, index + 1, columnCount - index);
-                temp [index] = cast(HFONT)-1;
                 item.cellFont = temp;
             }
         }
@@ -1435,7 +1552,18 @@
         } else {
             OS.SendMessage (handle, OS.LVM_SETCOLUMNWIDTH, 0, 0);
         }
-        if ((parent.style & DWT.VIRTUAL) is 0) {
+        /*
+        * Bug in Windows.  Despite the fact that every item in the
+        * table always has LPSTR_TEXTCALLBACK, Windows caches the
+        * bounds for the selected items.  This means that
+        * when you change the string to be something else, Windows
+        * correctly asks you for the new string but when the item
+        * is selected, the selection draws using the bounds of the
+        * previous item.  The fix is to reset LPSTR_TEXTCALLBACK
+        * even though it has not changed, causing Windows to flush
+        * cached bounds.
+        */
+        if ((style & DWT.VIRTUAL) is 0) {
             LVITEM lvItem;
             lvItem.mask = OS.LVIF_TEXT | OS.LVIF_IMAGE;
             lvItem.pszText = OS.LPSTR_TEXTCALLBACK;
@@ -1713,7 +1841,18 @@
                 OS.SendMessage (hwndHeader, OS.HDM_SETITEM, index, &hdItem);
             }
         }
-        if ((parent.style & DWT.VIRTUAL) is 0) {
+        /*
+        * Bug in Windows.  Despite the fact that every item in the
+        * table always has LPSTR_TEXTCALLBACK, Windows caches the
+        * bounds for the selected items.  This means that
+        * when you change the string to be something else, Windows
+        * correctly asks you for the new string but when the item
+        * is selected, the selection draws using the bounds of the
+        * previous item.  The fix is to reset LPSTR_TEXTCALLBACK
+        * even though it has not changed, causing Windows to flush
+        * cached bounds.
+        */
+        if ((style & DWT.VIRTUAL) is 0) {
             LVITEM lvItem;
             lvItem.mask = OS.LVIF_TEXT | OS.LVIF_IMAGE;
             lvItem.pszText = OS.LPSTR_TEXTCALLBACK;
@@ -1781,8 +1920,8 @@
                     item.cellForeground = temp;
                 }
                 if (item.cellFont !is null) {
-                    HFONT [] cellFont = item.cellFont;
-                    HFONT [] temp = new HFONT[]( columnCount );
+                    Font [] cellFont = item.cellFont;
+                    Font [] temp = new Font [columnCount];
                     System.arraycopy (cellFont, 0, temp, 0, index);
                     System.arraycopy (cellFont, index + 1, temp, index, columnCount - index);
                     item.cellFont = temp;
@@ -1861,7 +2000,7 @@
     if (index is count) return;
     setDeferResize (true);
     ignoreSelect = ignoreShrink = true;
-    int code = OS.SendMessage (handle, OS.LVM_DELETEITEM, index, 0);
+    int /*long*/ code = OS.SendMessage (handle, OS.LVM_DELETEITEM, index, 0);
     ignoreSelect = ignoreShrink = false;
     if (code is 0) error (DWT.ERROR_ITEM_NOT_REMOVED);
     System.arraycopy (items, index + 1, items, index, --count - index);
@@ -2186,8 +2325,33 @@
 public TableItem getItem (Point point) {
     checkWidget ();
     if (point is null) error (DWT.ERROR_NULL_ARGUMENT);
+    int count = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+    if (count is 0) return null;
     LVHITTESTINFO pinfo;
-    pinfo.pt.x = point.x;  pinfo.pt.y = point.y;
+    pinfo.pt.x = point.x;
+    pinfo.pt.y = point.y;
+    if ((style & DWT.FULL_SELECTION) is 0) {
+        if (hooks (DWT.MeasureItem)) {
+            OS.SendMessage (handle, OS.LVM_SUBITEMHITTEST, 0, &pinfo);
+            if (pinfo.iItem is -1) {
+                RECT rect;
+                rect.left = OS.LVIR_ICON;
+                ignoreCustomDraw = true;
+                int /*long*/ code = OS.SendMessage (handle, OS.LVM_GETITEMRECT, 0, &rect);
+                ignoreCustomDraw = false;
+                if (code !is 0) {
+                    pinfo.pt.x = rect.left;
+                    OS.SendMessage (handle, OS.LVM_SUBITEMHITTEST, 0, &pinfo);
+                }
+            }
+            if (pinfo.iItem !is -1 && pinfo.iSubItem is 0) {
+                if (hitTestSelection (pinfo.iItem, pinfo.pt.x, pinfo.pt.y)) {
+                    return _getItem (pinfo.iItem);
+                }
+            }
+            return null;
+        }
+    }
     OS.SendMessage (handle, OS.LVM_HITTEST, 0, &pinfo);
     if (pinfo.iItem !is -1) {
         /*
@@ -2235,7 +2399,7 @@
 
 /**
  * Returns the height of the area which would be used to
- * display <em>one</em> of the items in the receiver's.
+ * display <em>one</em> of the items in the receiver.
  *
  * @return the height of one item
  *
@@ -2246,9 +2410,9 @@
  */
 public int getItemHeight () {
     checkWidget ();
-    int empty = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 0, 0);
-    int oneItem = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 1, 0);
-    return (oneItem >> 16) - (empty >> 16);
+    int /*long*/ empty = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 0, 0);
+    int /*long*/ oneItem = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 1, 0);
+    return OS.HIWORD (oneItem) - OS.HIWORD (empty);
 }
 
 /**
@@ -2486,6 +2650,28 @@
     return false;
 }
 
+bool hitTestSelection (int index, int x, int y) {
+    int count = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+    if (count is 0) return false;
+    if (!hooks (DWT.MeasureItem)) return false;
+    bool result = false;
+    if (0 <= index && index < count) {
+        TableItem item = _getItem (index);
+        auto hDC = OS.GetDC (handle);
+        HFONT oldFont, newFont = cast(HFONT)OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+        if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
+        auto hFont = item.fontHandle (0);
+        if (hFont !is cast(HFONT)-1) hFont = OS.SelectObject (hDC, hFont);
+        Event event = sendMeasureItemEvent (item, index, 0, hDC);
+        if (event.getBounds ().contains (x, y)) result = true;
+        if (hFont !is cast(HFONT)-1) hFont = OS.SelectObject (hDC, hFont);
+        if (newFont !is null) OS.SelectObject (hDC, oldFont);
+        OS.ReleaseDC (handle, hDC);
+//      if (isDisposed () || item.isDisposed ()) return false;
+    }
+    return result;
+}
+
 int imageIndex (Image image, int column) {
     if (image is null) return OS.I_IMAGENONE;
     if (column is 0) {
@@ -2613,6 +2799,15 @@
     return -1;
 }
 
+bool isCustomToolTip () {
+    return hooks (DWT.MeasureItem);
+}
+
+bool isOptimizedRedraw () {
+    if ((style & DWT.H_SCROLL) is 0 || (style & DWT.V_SCROLL) is 0) return false;
+    return !hasChildren () && !hooks (DWT.Paint) && !filters (DWT.Paint);
+}
+
 /**
  * Returns <code>true</code> if the item is selected,
  * and <code>false</code> otherwise.  Indices out of
@@ -2744,7 +2939,7 @@
             TableItem item = items [index];
             if (item !is null && !item.isDisposed ()) item.release (false);
             ignoreSelect = ignoreShrink = true;
-            int code = OS.SendMessage (handle, OS.LVM_DELETEITEM, index, 0);
+            int /*long*/ code = OS.SendMessage (handle, OS.LVM_DELETEITEM, index, 0);
             ignoreSelect = ignoreShrink = false;
             if (code is 0) error (DWT.ERROR_ITEM_NOT_REMOVED);
             System.arraycopy (items, index + 1, items, index, --count - index);
@@ -2778,7 +2973,7 @@
     if (item !is null && !item.isDisposed ()) item.release (false);
     setDeferResize (true);
     ignoreSelect = ignoreShrink = true;
-    int code = OS.SendMessage (handle, OS.LVM_DELETEITEM, index, 0);
+    int /*long*/ code = OS.SendMessage (handle, OS.LVM_DELETEITEM, index, 0);
     ignoreSelect = ignoreShrink = false;
     if (code is 0) error (DWT.ERROR_ITEM_NOT_REMOVED);
     System.arraycopy (items, index + 1, items, index, --count - index);
@@ -2819,7 +3014,7 @@
             TableItem item = items [index];
             if (item !is null && !item.isDisposed ()) item.release (false);
             ignoreSelect = ignoreShrink = true;
-            int code = OS.SendMessage (handle, OS.LVM_DELETEITEM, start, 0);
+            int /*long*/ code = OS.SendMessage (handle, OS.LVM_DELETEITEM, start, 0);
             ignoreSelect = ignoreShrink = false;
             if (code is 0) break;
             index++;
@@ -2873,7 +3068,7 @@
         int index = itemCount - 1;
         while (index >= 0) {
             ignoreSelect = ignoreShrink = true;
-            int code = OS.SendMessage (handle, OS.LVM_DELETEITEM, index, 0);
+            int /*long*/ code = OS.SendMessage (handle, OS.LVM_DELETEITEM, index, 0);
             ignoreSelect = ignoreShrink = false;
             if (code is 0) break;
             --index;
@@ -2892,7 +3087,7 @@
         if (index !is -1) error (DWT.ERROR_ITEM_NOT_REMOVED);
     } else {
         ignoreSelect = ignoreShrink = true;
-        int code = OS.SendMessage (handle, OS.LVM_DELETEALLITEMS, 0, 0);
+        int /*long*/ code = OS.SendMessage (handle, OS.LVM_DELETEALLITEMS, 0, 0);
         ignoreSelect = ignoreShrink = false;
         if (code is 0) error (DWT.ERROR_ITEM_NOT_REMOVED);
     }
@@ -3067,10 +3262,8 @@
     ignoreSelect = false;
 }
 
-void sendEraseItemEvent (TableItem item, NMLVCUSTOMDRAW* nmcd, int lParam) {
+void sendEraseItemEvent (TableItem item, NMLVCUSTOMDRAW* nmcd, int lParam, Event measureEvent) {
     auto hDC = nmcd.nmcd.hdc;
-    auto hFont = item.cellFont !is null ? item.cellFont [nmcd.iSubItem] : cast(HFONT)-1;
-    if (hFont is cast(HFONT)-1) hFont = item.font;
     int clrText = item.cellForeground !is null ? item.cellForeground [nmcd.iSubItem] : -1;
     if (clrText is -1) clrText = item.foreground;
     int clrTextBk = -1;
@@ -3105,7 +3298,7 @@
     }
     if (OS.IsWindowEnabled (handle)) {
         if (selected && (nmcd.iSubItem is 0 || (style & DWT.FULL_SELECTION) !is 0)) {
-            if (OS.GetFocus () is handle) {
+            if (OS.GetFocus () is handle || display.getHighContrast ()) {
                 drawSelected = true;
                 data.foreground = OS.GetSysColor (OS.COLOR_HIGHLIGHTTEXT);
                 data.background = clrSelectionBk = OS.GetSysColor (OS.COLOR_HIGHLIGHT);
@@ -3120,16 +3313,17 @@
         } else {
             drawBackground = clrTextBk !is -1;
             /*
-            * Bug in Windows.  When LVM_SETTEXTBKCOLOR or LVM_SETBKCOLOR
-            * is used to set the background color of the the text or the
-            * control, the color is not set in the HDC that is provided
-            * in Custom Draw.  The fix is to explicitly set the background
-            * color.
+            * Bug in Windows.  When LVM_SETTEXTBKCOLOR, LVM_SETBKCOLOR
+            * or LVM_SETTEXTCOLOR is used to set the background color of
+            * the the text or the control, the color is not set in the HDC
+            * that is provided in Custom Draw.  The fix is to explicitly
+            * set the color.
             */
-            if (clrTextBk is -1) {
+            if (clrText is -1 || clrTextBk is -1) {
                 Control control = findBackgroundControl ();
                 if (control is null) control = this;
-                clrTextBk = control.getBackgroundPixel ();
+                if (clrText is -1) clrText = control.getForegroundPixel ();
+                if (clrTextBk is -1) clrTextBk = control.getBackgroundPixel ();
             }
             data.foreground = clrText !is -1 ? clrText : OS.GetTextColor (hDC);
             data.background = clrTextBk !is -1 ? clrTextBk : OS.GetBkColor (hDC);
@@ -3139,7 +3333,7 @@
         data.background = OS.GetSysColor (OS.COLOR_3DFACE);
         if (selected) clrSelectionBk = data.background;
     }
-    data.hFont = hFont;
+    data.font = item.getFont (nmcd.iSubItem);
     data.uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
     auto nSavedDC = OS.SaveDC (hDC);
     GC gc = GC.win32_new (hDC, data);
@@ -3158,6 +3352,7 @@
             }
         }
     }
+    bool focused = (event.detail & DWT.FOCUSED) !is 0;
     if (drawHot) event.detail |= DWT.HOT;
     if (drawSelected) event.detail |= DWT.SELECTED;
     if (drawBackground) event.detail |= DWT.BACKGROUND;
@@ -3196,10 +3391,7 @@
             OS.MoveMemory (lParam, nmcd, NMLVCUSTOMDRAW.sizeof);
         }
     }
-    if (ignoreDrawFocus) {
-        nmcd.nmcd.uItemState &= ~OS.CDIS_FOCUS;
-        OS.MoveMemory (lParam, nmcd, NMLVCUSTOMDRAW.sizeof);
-    }
+
     auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
     bool firstColumn = nmcd.iSubItem is OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, 0, 0);
     if (ignoreDrawForeground && ignoreDrawHot) {
@@ -3208,37 +3400,55 @@
             fillBackground (hDC, clrTextBk, &backgroundRect);
         }
     }
-    if (!ignoreDrawHot || (!ignoreDrawSelection && clrSelectionBk !is -1)) {
+    focusRect = null;
+    if (!ignoreDrawHot || !ignoreDrawSelection || !ignoreDrawFocus) {
+        bool fullText = (style & DWT.FULL_SELECTION) !is 0 || !firstColumn;
+        RECT textRect = item.getBounds (nmcd.nmcd.dwItemSpec, nmcd.iSubItem, true, false, fullText, false, hDC);
+        if ((style & DWT.FULL_SELECTION) is 0) {
+            if (measureEvent !is null) {
+                textRect.right = Math.min (cellRect.right, measureEvent.x + measureEvent.width);
+            }
+            if (!ignoreDrawFocus) {
+                nmcd.nmcd.uItemState &= ~OS.CDIS_FOCUS;
+                OS.MoveMemory (cast(void*)lParam, &nmcd, NMLVCUSTOMDRAW.sizeof);
+                focusRect = new RECT;
+                *focusRect = textRect;
+            }
+        }
         if (explorerTheme) {
-            bool hot = drawHot;
-            RECT pClipRect;
-            OS.SetRect (&pClipRect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom);
-            RECT rect;
-            OS.SetRect (&rect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom);
-            if ((style & DWT.FULL_SELECTION) !is 0) {
-                int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-                int index = OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, count - 1, 0);
-                RECT headerRect;
-                OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, &headerRect);
-                OS.MapWindowPoints (hwndHeader, handle, cast(POINT*) &headerRect, 2);
-                rect.left = 0;
-                rect.right = headerRect.right;
-                pClipRect.left = cellRect.left;
-                pClipRect.right += EXPLORER_EXTRA;
-            } else {
-                rect.right += EXPLORER_EXTRA;
-                pClipRect.right += EXPLORER_EXTRA;
+            if (!ignoreDrawHot || (!ignoreDrawSelection && clrSelectionBk !is -1)) {
+                bool hot = drawHot;
+                RECT pClipRect;
+                OS.SetRect (&pClipRect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom);
+                RECT rect;
+                OS.SetRect (&rect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom);
+                if ((style & DWT.FULL_SELECTION) !is 0) {
+                    int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
+                    int index = OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, count - 1, 0);
+                    RECT headerRect;
+                    OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, &headerRect);
+                    OS.MapWindowPoints (hwndHeader, handle, cast(POINT*) &headerRect, 2);
+                    rect.left = 0;
+                    rect.right = headerRect.right;
+                    pClipRect.left = cellRect.left;
+                    pClipRect.right += EXPLORER_EXTRA;
+                } else {
+                    rect.right += EXPLORER_EXTRA;
+                    pClipRect.right += EXPLORER_EXTRA;
+                }
+                auto hTheme = OS.OpenThemeData (handle, Display.LISTVIEW.ptr);
+                int iStateId = selected ? OS.LISS_SELECTED : OS.LISS_HOT;
+                if (OS.GetFocus () !is handle && selected && !hot) iStateId = OS.LISS_SELECTEDNOTFOCUS;
+                OS.DrawThemeBackground (hTheme, hDC, OS.LVP_LISTITEM, iStateId, &rect, &pClipRect);
+                OS.CloseThemeData (hTheme);
             }
-            auto hTheme = OS.OpenThemeData (handle, Display.LISTVIEW.ptr);
-            int iStateId = selected ? OS.LISS_SELECTED : OS.LISS_HOT;
-            if (OS.GetFocus () !is handle && selected && !hot) iStateId = OS.LISS_SELECTEDNOTFOCUS;
-            OS.DrawThemeBackground (hTheme, hDC, OS.LVP_LISTITEM, iStateId, &rect, &pClipRect);
-            OS.CloseThemeData (hTheme);
         } else {
-            bool fullText = ((style & DWT.FULL_SELECTION) !is 0 || !firstColumn);
-            RECT textRect = item.getBounds (nmcd.nmcd.dwItemSpec, nmcd.iSubItem, true, false, fullText, false, hDC);
-            fillBackground (hDC, clrSelectionBk, &textRect);
-        }
+            if (!ignoreDrawSelection && clrSelectionBk !is -1) fillBackground (hDC, clrSelectionBk, &textRect);
+        }
+    }
+    if (focused && ignoreDrawFocus) {
+        nmcd.nmcd.uItemState &= ~OS.CDIS_FOCUS;
+        OS.MoveMemory (lParam, nmcd, NMLVCUSTOMDRAW.sizeof);
     }
     if (ignoreDrawForeground) {
         RECT clipRect = item.getBounds (nmcd.nmcd.dwItemSpec, nmcd.iSubItem, true, true, true, false, hDC);
@@ -3248,13 +3458,40 @@
     }
 }
 
-Event sendMeasureItemEvent (TableItem item, int row, int column, HDC hDC) {
-    auto hFont = item.cellFont !is null ? item.cellFont [column] : cast(HFONT)-1;
-    if (hFont is cast(HFONT)-1) hFont = item.font;
+Event sendEraseItemEvent (TableItem item, NMTTCUSTOMDRAW* nmcd, int column, RECT* cellRect) {
+    int nSavedDC = OS.SaveDC (nmcd.nmcd.hdc);
+    RECT* insetRect = toolTipInset (cellRect);
+    OS.SetWindowOrgEx (nmcd.nmcd.hdc, insetRect.left, insetRect.top, null);
     GCData data = new GCData ();
     data.device = display;
-    data.hFont = hFont;
-    auto nSavedDC = OS.SaveDC (hDC);
+    data.foreground = OS.GetTextColor (nmcd.nmcd.hdc);
+    data.background = OS.GetBkColor (nmcd.nmcd.hdc);
+    data.font = item.getFont (column);
+    data.uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
+    GC gc = GC.win32_new (nmcd.nmcd.hdc, data);
+    Event event = new Event ();
+    event.item = item;
+    event.index = column;
+    event.gc = gc;
+    event.detail |= DWT.FOREGROUND;
+    event.x = cellRect.left;
+    event.y = cellRect.top;
+    event.width = cellRect.right - cellRect.left;
+    event.height = cellRect.bottom - cellRect.top;
+    //gc.setClipping (event.x, event.y, event.width, event.height);
+    sendEvent (DWT.EraseItem, event);
+    event.gc = null;
+    //int newTextClr = data.foreground;
+    gc.dispose ();
+    OS.RestoreDC (nmcd.nmcd.hdc, nSavedDC);
+    return event;
+}
+
+Event sendMeasureItemEvent (TableItem item, int row, int column, HDC hDC) {
+    GCData data = new GCData ();
+    data.device = display;
+    data.font = item.getFont (column);
+    int nSavedDC = OS.SaveDC (hDC);
     GC gc = GC.win32_new (hDC, data);
     RECT itemRect = item.getBounds (row, column, true, true, false, false, hDC);
     Event event = new Event ();
@@ -3281,7 +3518,16 @@
     return event;
 }
 
-LRESULT sendMouseDownEvent (int type, int button, int msg, int wParam, int lParam) {
+LRESULT sendMouseDownEvent (int type, int button, int msg, int /*long*/ wParam, int /*long*/ lParam) {
+    Display display = this.display;
+    display.captureChanged = false;
+    if (!sendMouseEvent (type, button, handle, msg, wParam, lParam)) {
+        if (!display.captureChanged && !isDisposed ()) {
+            if (OS.GetCapture () !is handle) OS.SetCapture (handle);
+        }
+        return LRESULT.ZERO;
+    }
+
     /*
     * Feature in Windows.  Inside WM_LBUTTONDOWN and WM_RBUTTONDOWN,
     * the widget starts a modal loop to determine if the user wants
@@ -3295,16 +3541,30 @@
     * the widget does not eat the mouse up.
     */
     LVHITTESTINFO pinfo;
-    pinfo.pt.x = cast(short) (lParam & 0xFFFF);
-    pinfo.pt.y = cast(short) (lParam >> 16);
+    pinfo.pt.x = OS.GET_X_LPARAM (lParam);
+    pinfo.pt.y = OS.GET_Y_LPARAM (lParam);
     OS.SendMessage (handle, OS.LVM_HITTEST, 0, &pinfo);
-    Display display = this.display;
-    display.captureChanged = false;
-    if (!sendMouseEvent (type, button, handle, msg, wParam, lParam)) {
-        if (!display.captureChanged && !isDisposed ()) {
-            if (OS.GetCapture () !is handle) OS.SetCapture (handle);
-        }
-        return LRESULT.ZERO;
+    if ((style & DWT.FULL_SELECTION) is 0) {
+        if (hooks (DWT.MeasureItem)) {
+            OS.SendMessage (handle, OS.LVM_SUBITEMHITTEST, 0, &pinfo);
+            if (pinfo.iItem is -1) {
+                int count = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+                if (count !is 0) {
+                    RECT rect;
+                    rect.left = OS.LVIR_ICON;
+                    ignoreCustomDraw = true;
+                    int /*long*/ code = OS.SendMessage (handle, OS.LVM_GETITEMRECT, 0, &rect);
+                    ignoreCustomDraw = false;
+                    if (code !is 0) {
+                        pinfo.pt.x = rect.left;
+                        OS.SendMessage (handle, OS.LVM_SUBITEMHITTEST, 0, &pinfo);
+                        pinfo.flags &= ~(OS.LVHT_ONITEMICON | OS.LVHT_ONITEMLABEL);
+                    }
+                }
+            } else {
+                if (pinfo.iSubItem !is 0) pinfo.iItem = -1;
+            }
+        }
     }
 
     /*
@@ -3354,6 +3614,21 @@
             forceSelect = true;
         }
     }
+
+    /* Determine whether the user has selected an item based on DWT.MeasureItem */
+    fullRowSelect = false;
+    if (pinfo.iItem !is -1) {
+        if ((style & DWT.FULL_SELECTION) is 0) {
+            if (hooks (DWT.MeasureItem)) {
+                fullRowSelect = hitTestSelection (pinfo.iItem, pinfo.pt.x, pinfo.pt.y);
+                if (fullRowSelect) {
+                    int flags = OS.LVHT_ONITEMICON | OS.LVHT_ONITEMLABEL;
+                    if ((pinfo.flags & flags) !is 0) fullRowSelect = false;
+                }
+            }
+        }
+    }
+
     /*
     * Feature in Windows.  Inside WM_LBUTTONDOWN and WM_RBUTTONDOWN,
     * the widget starts a modal loop to determine if the user wants
@@ -3366,11 +3641,31 @@
     if (!dragDetect) {
         int flags = OS.LVHT_ONITEMICON | OS.LVHT_ONITEMLABEL;
         dragDetect = pinfo.iItem is -1 || (pinfo.flags & flags) is 0;
-    }
+        if (fullRowSelect) dragDetect = true;
+    }
+
+    /*
+    * Temporarily set LVS_EX_FULLROWSELECT to allow drag and drop
+    * and the mouse to manipulate items based on the results of
+    * the DWT.MeasureItem event.
+    */
+    if (fullRowSelect) {
+        OS.UpdateWindow (handle);
+        OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+        OS.SendMessage (handle, OS.LVM_SETEXTENDEDLISTVIEWSTYLE, OS.LVS_EX_FULLROWSELECT, OS.LVS_EX_FULLROWSELECT);
+    }
+    dragStarted = false;
+    display.dragCancelled = false;
     if (!dragDetect) display.runDragDrop = false;
-    int code = callWindowProc (handle, msg, wParam, lParam, forceSelect);
+    int /*long*/ code = callWindowProc (handle, msg, wParam, lParam, forceSelect);
     if (!dragDetect) display.runDragDrop = true;
-    if (dragStarted || !dragDetect) {
+    if (fullRowSelect) {
+        fullRowSelect = false;
+        OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+        OS.SendMessage (handle, OS.LVM_SETEXTENDEDLISTVIEWSTYLE, OS.LVS_EX_FULLROWSELECT, 0);
+    }
+
+    if (dragStarted || display.dragCancelled) {
         if (!display.captureChanged && !isDisposed ()) {
             if (OS.GetCapture () !is handle) OS.SetCapture (handle);
         }
@@ -3384,7 +3679,6 @@
             sendMouseEvent (DWT.MouseUp, button, handle, msg, wParam, lParam);
         }
     }
-    dragStarted = false;
     return new LRESULT (code);
 }
 
@@ -3392,9 +3686,7 @@
     auto hDC = nmcd.nmcd.hdc;
     GCData data = new GCData ();
     data.device = display;
-    auto hFont = item.cellFont !is null ? item.cellFont [nmcd.iSubItem] : cast(HFONT)-1;
-    if (hFont is cast(HFONT)-1) hFont = item.font;
-    data.hFont = hFont;
+    data.font = item.getFont (nmcd.iSubItem);
     /*
     * Bug in Windows.  For some reason, CDIS_SELECTED always set,
     * even for items that are not selected.  The fix is to get
@@ -3412,7 +3704,7 @@
     }
     if (OS.IsWindowEnabled (handle)) {
         if (selected && (nmcd.iSubItem is 0 || (style & DWT.FULL_SELECTION) !is 0)) {
-            if (OS.GetFocus () is handle) {
+            if (OS.GetFocus () is handle || display.getHighContrast ()) {
                 drawSelected = true;
                 if (selectionForeground !is -1) {
                     data.foreground = selectionForeground;
@@ -3437,16 +3729,17 @@
             if (clrTextBk is -1) clrTextBk = item.background;
             drawBackground = clrTextBk !is -1;
             /*
-            * Bug in Windows.  When LVM_SETTEXTBKCOLOR or LVM_SETBKCOLOR
-            * is used to set the background color of the the text or the
-            * control, the color is not set in the HDC that is provided
-            * in Custom Draw.  The fix is to explicitly set the background
-            * color.
+            * Bug in Windows.  When LVM_SETTEXTBKCOLOR, LVM_SETBKCOLOR
+            * or LVM_SETTEXTCOLOR is used to set the background color of
+            * the the text or the control, the color is not set in the HDC
+            * that is provided in Custom Draw.  The fix is to explicitly
+            * set the color.
             */
-            if (clrTextBk is -1) {
+            if (clrText is -1 || clrTextBk is -1) {
                 Control control = findBackgroundControl ();
                 if (control is null) control = this;
-                clrTextBk = control.getBackgroundPixel ();
+                if (clrText is -1) clrText = control.getForegroundPixel ();
+                if (clrTextBk is -1) clrTextBk = control.getBackgroundPixel ();
             }
             data.foreground = clrText !is -1 ? clrText : OS.GetTextColor (hDC);
             data.background = clrTextBk !is -1 ? clrTextBk : OS.GetBkColor (hDC);
@@ -3485,21 +3778,56 @@
     int cellHeight = cellRect.bottom - cellRect.top;
     gc.setClipping (cellRect.left, cellRect.top, cellWidth, cellHeight);
     sendEvent (DWT.PaintItem, event);
+    if (data.focusDrawn) focusRect = null;
     event.gc = null;
     gc.dispose ();
     OS.RestoreDC (hDC, nSavedDC);
 }
 
-override void setBackgroundImage (HBITMAP hBitmap) {
+Event sendPaintItemEvent (TableItem item, NMTTCUSTOMDRAW* nmcd, int column, RECT* itemRect) {
+    int nSavedDC = OS.SaveDC (nmcd.nmcd.hdc);
+    RECT* insetRect = toolTipInset (itemRect);
+    OS.SetWindowOrgEx (nmcd.nmcd.hdc, insetRect.left, insetRect.top, null);
+    GCData data = new GCData ();
+    data.device = display;
+    data.font = item.getFont (column);
+    data.foreground = OS.GetTextColor (nmcd.nmcd.hdc);
+    data.background = OS.GetBkColor (nmcd.nmcd.hdc);
+    data.uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
+    GC gc = GC.win32_new (nmcd.nmcd.hdc, data);
+    Event event = new Event ();
+    event.item = item;
+    event.index = column;
+    event.gc = gc;
+    event.detail |= DWT.FOREGROUND;
+    event.x = itemRect.left;
+    event.y = itemRect.top;
+    event.width = itemRect.right - itemRect.left;
+    event.height = itemRect.bottom - itemRect.top;
+    //gc.setClipping (cellRect.left, cellRect.top, cellWidth, cellHeight);
+    sendEvent (DWT.PaintItem, event);
+    event.gc = null;
+    gc.dispose ();
+    OS.RestoreDC (nmcd.nmcd.hdc, nSavedDC);
+    return event;
+}
+
+void setBackgroundImage (HBITMAP hBitmap) {
     super.setBackgroundImage (hBitmap);
-    if (!customDraw) setBackgroundTransparent (hBitmap !is null);
+    if (hBitmap !is null) {
+        setBackgroundTransparent (true);
+    } else {
+        if (!hooks (DWT.MeasureItem) && !hooks (DWT.EraseItem) && !hooks (DWT.PaintItem)) {
+            setBackgroundTransparent (false);
+        }
+    }
 }
 
 override void setBackgroundPixel (int newPixel) {
-    if (!customDraw) {
+    int oldPixel = OS.SendMessage (handle, OS.LVM_GETBKCOLOR, 0, 0);
+    if (oldPixel !is OS.CLR_NONE) {
         if (findImageControl () !is null) return;
         if (newPixel is -1) newPixel = defaultBackground ();
-        int oldPixel = OS.SendMessage (handle, OS.LVM_GETBKCOLOR, 0, 0);
         if (oldPixel !is newPixel) {
             OS.SendMessage (handle, OS.LVM_SETBKCOLOR, 0, newPixel);
             OS.SendMessage (handle, OS.LVM_SETTEXTBKCOLOR, 0, newPixel);
@@ -3565,7 +3893,11 @@
             Control control = findBackgroundControl ();
             if (control is null) control = this;
             if (control.backgroundImage is null) {
-                setBackgroundPixel (control.getBackgroundPixel ());
+                int newPixel = control.getBackgroundPixel ();
+                OS.SendMessage (handle, OS.LVM_SETBKCOLOR, 0, newPixel);
+                OS.SendMessage (handle, OS.LVM_SETTEXTBKCOLOR, 0, newPixel);
+                if ((style & DWT.CHECK) !is 0) fixCheckboxImageListColor (true);
+                OS.InvalidateRect (handle, null, true);
             }
 
             /* Set LVS_EX_FULLROWSELECT */
@@ -3701,9 +4033,16 @@
     if (defer) {
         if (resizeCount++ is 0) {
             wasResized = false;
+            /*
+            * Feature in Windows.  When LVM_SETBKCOLOR is used with CLR_NONE
+            * to make the background of the table transparent, drawing becomes
+            * slow.  The fix is to temporarily clear CLR_NONE when redraw is
+            * turned off.
+            */
             if (hooks (DWT.MeasureItem) || hooks (DWT.EraseItem) || hooks (DWT.PaintItem)) {
                 if (drawCount++ is 0 && OS.IsWindowVisible (handle)) {
                     OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+                    OS.SendMessage (handle, OS.LVM_SETBKCOLOR, 0, 0xFFFFFF);
                 }
             }
         }
@@ -3711,6 +4050,7 @@
         if (--resizeCount is 0) {
             if (hooks (DWT.MeasureItem) || hooks (DWT.EraseItem) || hooks (DWT.PaintItem)) {
                 if (--drawCount is 0 /*&& OS.IsWindowVisible (handle)*/) {
+                    OS.SendMessage (handle, OS.LVM_SETBKCOLOR, 0, OS.CLR_NONE);
                     OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
                     static if (OS.IsWinCE) {
                         auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
@@ -4004,7 +4344,7 @@
         if (item !is null && !item.isDisposed ()) item.release (false);
         if (!isVirtual) {
             ignoreSelect = ignoreShrink = true;
-            int code = OS.SendMessage (handle, OS.LVM_DELETEITEM, count, 0);
+            int /*long*/ code = OS.SendMessage (handle, OS.LVM_DELETEITEM, count, 0);
             ignoreSelect = ignoreShrink = false;
             if (code is 0) break;
         }
@@ -4241,25 +4581,23 @@
         int itemCount = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
         while (index < itemCount) {
             String string = null;
-            HFONT font = cast(HFONT)-1;
+            HFONT hFont = cast(HFONT)-1;
             if (item !is null) {
                 string = item.text;
                 imageIndent = Math.max (imageIndent, item.imageIndent);
-                if (item.cellFont !is null) font = item.cellFont [0];
-                if (font is cast(HFONT)-1) font = item.font;
+                hFont = item.fontHandle (0);
             } else {
                 if (items [index] !is null) {
                     TableItem tableItem = items [index];
                     string = tableItem.text;
                     imageIndent = Math.max (imageIndent, tableItem.imageIndent);
-                    if (tableItem.cellFont !is null) font = tableItem.cellFont [0];
-                    if (font is cast(HFONT)-1) font = tableItem.font;
+                    hFont = tableItem.fontHandle (0);
                 }
             }
             if (string !is null && string.length !is 0) {
-                if (font !is cast(HFONT)-1) {
+                if (hFont !is cast(HFONT)-1) {
                     auto hDC = OS.GetDC (handle);
-                    auto oldFont = OS.SelectObject (hDC, font);
+                    auto oldFont = OS.SelectObject (hDC, hFont);
                     int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE | OS.DT_NOPREFIX;
                     TCHAR[] buffer = StrToTCHARs (getCodePage (), string, false);
                     RECT rect;
@@ -4865,8 +5203,31 @@
     super.subclass ();
     if (HeaderProc !is null) {
         auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
-        OS.SetWindowLong (hwndHeader, OS.GWL_WNDPROC, display.windowProc);
-    }
+        OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, display.windowProc);
+    }
+}
+
+RECT* toolTipInset (RECT* rect) {
+    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+        RECT* insetRect = new RECT;
+        OS.SetRect (insetRect, rect.left - 1, rect.top - 1, rect.right + 1, rect.bottom + 1);
+        return insetRect;
+    }
+    return rect;
+}
+
+RECT* toolTipRect (RECT* rect) {
+    RECT* toolRect = new RECT;
+    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+        OS.SetRect (toolRect, rect.left - 1, rect.top - 1, rect.right + 1, rect.bottom + 1);
+    } else {
+        HWND hwndToolTip = cast(HWND)OS.SendMessage (handle, OS.LVM_GETTOOLTIPS, 0, 0);
+        OS.SetRect (toolRect, rect.left, rect.top, rect.right, rect.bottom);
+        int dwStyle = OS.GetWindowLong (hwndToolTip, OS.GWL_STYLE);
+        int dwExStyle = OS.GetWindowLong (hwndToolTip, OS.GWL_EXSTYLE);
+        OS.AdjustWindowRectEx (toolRect, dwStyle, false, dwExStyle);
+    }
+    return toolRect;
 }
 
 override String toolTipText (NMTTDISPINFO* hdr) {
@@ -4885,7 +5246,7 @@
     super.unsubclass ();
     if (HeaderProc !is null) {
         auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
-        OS.SetWindowLong (hwndHeader, OS.GWL_WNDPROC, cast(int) HeaderProc);
+        OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, cast(LONG_PTR)HeaderProc);
     }
 }
 
@@ -4904,15 +5265,15 @@
     */
     WNDPROC oldHeaderProc, oldTableProc;
     auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
-    bool fixSubclass = !hasChildren () && !hooks (DWT.Paint) && !filters (DWT.Paint);
+    bool fixSubclass = isOptimizedRedraw ();
     if (fixSubclass) {
-        oldTableProc = cast(WNDPROC) OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) TableProc);
-        oldHeaderProc = cast(WNDPROC) OS.SetWindowLong (hwndHeader, OS.GWL_WNDPROC, cast(int) HeaderProc);
+        oldTableProc = cast(WNDPROC)OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TableProc);
+        oldHeaderProc = cast(WNDPROC)OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, cast(LONG_PTR)HeaderProc);
     }
     super.update (all);
     if (fixSubclass) {
-        OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) oldTableProc);
-        OS.SetWindowLong (hwndHeader, OS.GWL_WNDPROC, cast(int) oldHeaderProc);
+        OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)oldTableProc);
+        OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, cast(LONG_PTR)oldHeaderProc);
     }
 }
 
@@ -5044,13 +5405,12 @@
             }
             case OS.WM_SETCURSOR: {
                 if (wParam is cast(int)hwnd) {
-                    int hitTest = cast(short) (lParam & 0xFFFF);
+                    int hitTest = cast(short) OS.LOWORD (lParam);
                     if (hitTest is OS.HTCLIENT) {
                         HDHITTESTINFO pinfo;
                         int pos = OS.GetMessagePos ();
                         POINT pt;
-                        pt.x = cast(short) (pos & 0xFFFF);
-                        pt.y = cast(short) (pos >> 16);
+                        OS.POINTSTOPOINT (pt, pos);
                         OS.ScreenToClient (hwnd, &pt);
                         pinfo.pt.x = pt.x;
                         pinfo.pt.y = pt.y;
@@ -5070,6 +5430,19 @@
         }
         return callWindowProc (hwnd, msg, wParam, lParam);
     }
+    if (msg is Display.DI_GETDRAGIMAGE) {
+        /*
+        * Bug in Windows.  For some reason, DI_GETDRAGIMAGE
+        * returns an image that does not contain strings.
+        * The fix is to disable the table window proc.
+        *
+        * NOTE: This only happens on Vista.
+        */
+        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) return 0;
+        //TEMPORARY CODE
+        if (hooks (DWT.EraseItem) || hooks (DWT.PaintItem)) return 0;
+//      if (getSelectionCount () !is 1) return 0;
+    }
     return super.windowProc (hwnd, msg, wParam, lParam);
 }
 
@@ -5094,7 +5467,7 @@
             * This allows the application to cancel an operation that is normally
             * performed in WM_KEYDOWN from WM_CHAR.
             */
-            int code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam);
+            int /*long*/ code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam);
             return new LRESULT (code);
         case DWT.CR:
             /*
@@ -5203,18 +5576,18 @@
             * NOTE: The header tooltip can subclass the header proc so the
             * current proc must be restored or header tooltips stop working.
             */
-            int oldHeaderProc = 0, oldTableProc = 0;
+            int /*long*/ oldHeaderProc = 0, oldTableProc = 0;
             auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
-            bool fixSubclass = !hasChildren () && !hooks (DWT.Paint) && !filters (DWT.Paint);
+            bool fixSubclass = isOptimizedRedraw ();
             if (fixSubclass) {
-                oldTableProc = OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) TableProc);
-                oldHeaderProc = OS.SetWindowLong (hwndHeader, OS.GWL_WNDPROC, cast(int) HeaderProc);
+                oldTableProc = OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TableProc);
+                oldHeaderProc = OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, cast(LONG_PTR)HeaderProc);
             }
-            int code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam);
+            int /*long*/ code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam);
             result = code is 0 ? LRESULT.ZERO : new LRESULT (code);
             if (fixSubclass) {
-                OS.SetWindowLong (handle, OS.GWL_WNDPROC, oldTableProc);
-                OS.SetWindowLong (hwndHeader, OS.GWL_WNDPROC, oldHeaderProc);
+                OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldTableProc);
+                OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, oldHeaderProc);
             }
             //FALL THROUGH
         case OS.VK_UP:
@@ -5250,8 +5623,8 @@
     * case and avoid calling the window proc.
     */
     LVHITTESTINFO pinfo;
-    pinfo.pt.x = cast(short) (lParam & 0xFFFF);
-    pinfo.pt.y = cast(short) (lParam >> 16);
+    pinfo.pt.x = OS.GET_X_LPARAM (lParam);
+    pinfo.pt.y = OS.GET_Y_LPARAM (lParam);
     int index = OS.SendMessage (handle, OS.LVM_HITTEST, 0, &pinfo);
     Display display = this.display;
     display.captureChanged = false;
@@ -5302,8 +5675,8 @@
     /* Look for check/uncheck */
     if ((style & DWT.CHECK) !is 0) {
         LVHITTESTINFO pinfo;
-        pinfo.pt.x = cast(short) (lParam & 0xFFFF);
-        pinfo.pt.y = cast(short) (lParam >> 16);
+        pinfo.pt.x = OS.GET_X_LPARAM (lParam);
+        pinfo.pt.y = OS.GET_Y_LPARAM (lParam);
         /*
         * Note that when the table has LVS_EX_FULLROWSELECT and the
         * user clicks anywhere on a row except on the check box, all
@@ -5422,8 +5795,8 @@
     * case and avoid calling the window proc.
     */
     LVHITTESTINFO pinfo;
-    pinfo.pt.x = cast(short) (lParam & 0xFFFF);
-    pinfo.pt.y = cast(short) (lParam >> 16);
+    pinfo.pt.x = OS.GET_X_LPARAM (lParam);
+    pinfo.pt.y = OS.GET_Y_LPARAM (lParam);
     OS.SendMessage (handle, OS.LVM_HITTEST, 0, &pinfo);
     Display display = this.display;
     display.captureChanged = false;
@@ -5507,7 +5880,32 @@
     return result;
 }
 
-override LRESULT WM_SIZE (int wParam, int lParam) {
+override LRESULT WM_SETREDRAW (int wParam, int lParam) {
+    LRESULT result = super.WM_SETREDRAW (wParam, lParam);
+    if (result !is null) return result;
+    /*
+    * Feature in Windows.  When LVM_SETBKCOLOR is used with CLR_NONE
+    * to make the background of the table transparent, drawing becomes
+    * slow.  The fix is to temporarily clear CLR_NONE when redraw is
+    * turned off.
+    */
+    if (wParam is 1) {
+        if (OS.SendMessage (handle, OS.LVM_GETBKCOLOR, 0, 0) !is OS.CLR_NONE) {
+            if (hooks (DWT.MeasureItem) || hooks (DWT.EraseItem) || hooks (DWT.PaintItem)) {
+                OS.SendMessage (handle, OS.LVM_SETBKCOLOR, 0, OS.CLR_NONE);
+            }
+        }
+    }
+    int /*long*/ code = callWindowProc (handle, OS.WM_SETREDRAW, wParam, lParam);
+    if (wParam is 0) {
+        if (OS.SendMessage (handle, OS.LVM_GETBKCOLOR, 0, 0) is OS.CLR_NONE) {
+            OS.SendMessage (handle, OS.LVM_SETBKCOLOR, 0, 0xFFFFFF);
+        }
+    }
+    return code is 0 ? LRESULT.ZERO : new LRESULT (code);
+}
+
+override LRESULT WM_SIZE (int /*long*/ wParam, int /*long*/ lParam) {
     if (ignoreResize) return null;
     if (hooks (DWT.EraseItem) || hooks (DWT.PaintItem)) {
         OS.InvalidateRect (handle, null, true);
@@ -5525,8 +5923,11 @@
     if (findBackgroundControl () is null) {
         setBackgroundPixel (defaultBackground ());
     } else {
-        if ((style & DWT.CHECK) !is 0) {
-            fixCheckboxImageListColor (true);
+        int oldPixel = OS.SendMessage (handle, OS.LVM_GETBKCOLOR, 0, 0);
+        if (oldPixel !is OS.CLR_NONE) {
+            if (findImageControl () is null) {
+                if ((style & DWT.CHECK) !is 0) fixCheckboxImageListColor (true);
+            }
         }
     }
     return result;
@@ -5551,27 +5952,78 @@
     }
 
     /*
-    * When there are many columns in a table, scrolling performance
-    * can be improved by temporarily unsubclassing the window proc
-    * so that internal messages are dispatched directly to the table.
-    * If the application expects to see a paint event or has a child
-    * whose font, foreground or background color might be needed,
-    * the window proc cannot be unsubclassed
+    * Feature in Windows.  When there are many columns in a table,
+    * scrolling performance can be improved by unsubclassing the
+    * window proc so that internal messages are dispatched directly
+    * to the table.  If the application expects to see a paint event
+    * or has a child whose font, foreground or background color might
+    * be needed, the window proc cannot be unsubclassed
     *
     * NOTE: The header tooltip can subclass the header proc so the
     * current proc must be restored or header tooltips stop working.
     */
-    int oldHeaderProc = 0, oldTableProc = 0;
+    WNDPROC oldHeaderProc, oldTableProc;
     auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
-    bool fixSubclass = !hasChildren () && !hooks (DWT.Paint) && !filters (DWT.Paint);
+    bool fixSubclass = isOptimizedRedraw ();
     if (fixSubclass) {
-        oldTableProc = OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int)TableProc);
-        oldHeaderProc = OS.SetWindowLong (hwndHeader, OS.GWL_WNDPROC, cast(int)HeaderProc);
-    }
+        oldTableProc = cast(WNDPROC)OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TableProc);
+        oldHeaderProc = cast(WNDPROC)OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, cast(LONG_PTR)HeaderProc);
+    }
+
+    /*
+    * Feature in Windows.  For some reason, when the table window
+    * proc processes WM_HSCROLL or WM_VSCROLL when there are many
+    * columns in the table, scrolling is slow and the table does
+    * not keep up with the position of the scroll bar.  The fix
+    * is to turn off redraw, scroll, turn redraw back on and redraw
+    * the entire table.  Strangly, redrawing the entire table is
+    * faster.
+    */
+    bool fixScroll = false;
+    if (OS.LOWORD (wParam) !is OS.SB_ENDSCROLL) {
+        if (OS.COMCTL32_MAJOR >= 6) {
+            if (columnCount > H_SCROLL_LIMIT) {
+                int rowCount = OS.SendMessage (handle, OS.LVM_GETCOUNTPERPAGE, 0, 0);
+                if (rowCount > V_SCROLL_LIMIT) fixScroll = drawCount is 0 && OS.IsWindowVisible (handle);
+            }
+        }
+    }
+    if (fixScroll) OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
     LRESULT result = super.WM_HSCROLL (wParam, lParam);
+    if (fixScroll) {
+        OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+        int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_ALLCHILDREN;
+        OS.RedrawWindow (handle, null, null, flags);
+        /*
+        * Feature in Windows.  On Vista only, it is faster to
+        * compute and answer the data for the visible columns
+        * of a table when scrolling, rather than just return
+        * the data for each column when asked.
+        */
+        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+            RECT headerRect, rect;
+            OS.GetClientRect (handle, &rect);
+            bool [] visible = new bool [columnCount];
+            for (int i=0; i<columnCount; i++) {
+                visible [i] = true;
+                if (OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, i, &headerRect) !is 0) {
+                    OS.MapWindowPoints (hwndHeader, handle, cast(POINT*)&headerRect, 2);
+                    visible [i] = OS.IntersectRect(&headerRect, &rect, &headerRect) !is 0;
+                }
+            }
+            try {
+                display.hwndParent = OS.GetParent (handle);
+                display.columnVisible = visible;
+                OS.UpdateWindow (handle);
+            } finally {
+                display.columnVisible = null;
+            }
+        }
+    }
+
     if (fixSubclass) {
-        OS.SetWindowLong (handle, OS.GWL_WNDPROC, oldTableProc);
-        OS.SetWindowLong (hwndHeader, OS.GWL_WNDPROC, oldHeaderProc);
+        OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)oldTableProc);
+        OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, cast(LONG_PTR)oldHeaderProc);
     }
 
     /*
@@ -5609,17 +6061,68 @@
     * NOTE: The header tooltip can subclass the header proc so the
     * current proc must be restored or header tooltips stop working.
     */
-    int oldHeaderProc = 0, oldTableProc = 0;
+    WNDPROC oldHeaderProc, oldTableProc;
     auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
-    bool fixSubclass = !hasChildren () && !hooks (DWT.Paint) && !filters (DWT.Paint);
+    bool fixSubclass = isOptimizedRedraw ();
     if (fixSubclass) {
-        oldTableProc = OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) TableProc);
-        oldHeaderProc = OS.SetWindowLong (hwndHeader, OS.GWL_WNDPROC, cast(int) HeaderProc);
-    }
+        oldTableProc = cast(WNDPROC)OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TableProc);
+        oldHeaderProc = cast(WNDPROC)OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, cast(LONG_PTR)HeaderProc);
+    }
+
+    /*
+    * Feature in Windows.  For some reason, when the table window
+    * proc processes WM_HSCROLL or WM_VSCROLL when there are many
+    * columns in the table, scrolling is slow and the table does
+    * not keep up with the position of the scroll bar.  The fix
+    * is to turn off redraw, scroll, turn redraw back on and redraw
+    * the entire table.  Strangly, redrawing the entire table is
+    * faster.
+    */
+    bool fixScroll = false;
+    if (OS.LOWORD (wParam) !is OS.SB_ENDSCROLL) {
+        if (OS.COMCTL32_MAJOR >= 6) {
+            if (columnCount > H_SCROLL_LIMIT) {
+                int rowCount = OS.SendMessage (handle, OS.LVM_GETCOUNTPERPAGE, 0, 0);
+                if (rowCount > V_SCROLL_LIMIT) fixScroll = drawCount is 0 && OS.IsWindowVisible (handle);
+            }
+        }
+    }
+    if (fixScroll) OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
     LRESULT result = super.WM_VSCROLL (wParam, lParam);
+    if (fixScroll) {
+        OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+        int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_ALLCHILDREN;
+        OS.RedrawWindow (handle, null, null, flags);
+        /*
+        * Feature in Windows.  On Vista only, it is faster to
+        * compute and answer the data for the visible columns
+        * of a table when scrolling, rather than just return
+        * the data for each column when asked.
+        */
+        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+            RECT headerRect, rect;
+            OS.GetClientRect (handle, &rect);
+            bool [] visible = new bool [columnCount];
+            for (int i=0; i<columnCount; i++) {
+                visible [i] = true;
+                if (OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, i, &headerRect) !is 0) {
+                    OS.MapWindowPoints (hwndHeader, handle, cast(POINT*)&headerRect, 2);
+                    visible [i] = OS.IntersectRect(&headerRect, &rect, &headerRect) !is 0;
+                }
+            }
+            try {
+                display.hwndParent = OS.GetParent (handle);
+                display.columnVisible = visible;
+                OS.UpdateWindow (handle);
+            } finally {
+                display.columnVisible = null;
+            }
+        }
+    }
+
     if (fixSubclass) {
-        OS.SetWindowLong (handle, OS.GWL_WNDPROC, oldTableProc);
-        OS.SetWindowLong (hwndHeader, OS.GWL_WNDPROC, oldHeaderProc);
+        OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)oldTableProc);
+        OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, cast(LONG_PTR)oldHeaderProc);
     }
 
     /*
@@ -5630,7 +6133,7 @@
     */
     int bits = OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
     if ((bits & OS.LVS_EX_GRIDLINES) !is 0) {
-        int code = wParam & 0xFFFF;
+        int code = OS.LOWORD (wParam);
         switch (code) {
             case OS.SB_ENDSCROLL:
             case OS.SB_THUMBPOSITION:
@@ -5646,9 +6149,9 @@
                 RECT clientRect;
                 OS.GetClientRect (handle, &clientRect);
                 clientRect.top += headerHeight;
-                int empty = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 0, 0);
-                int oneItem = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 1, 0);
-                int itemHeight = (oneItem >> 16) - (empty >> 16);
+                int /*long*/ empty = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 0, 0);
+                int /*long*/ oneItem = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 1, 0);
+                int itemHeight = OS.HIWORD (oneItem) - OS.HIWORD (empty);
                 if (code is OS.SB_LINEDOWN) {
                     clientRect.top = clientRect.bottom - itemHeight - GRID_WIDTH;
                 } else {
@@ -5670,9 +6173,9 @@
     MEASUREITEMSTRUCT* struct_ = cast(MEASUREITEMSTRUCT*)lParam;
     //OS.MoveMemory (struct_, lParam, MEASUREITEMSTRUCT.sizeof);
     if (itemHeight is -1) {
-        int empty = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 0, 0);
-        int oneItem = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 1, 0);
-        struct_.itemHeight = (oneItem >> 16) - (empty >> 16);
+        int /*long*/ empty = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 0, 0);
+        int /*long*/ oneItem = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 1, 0);
+        struct_.itemHeight = OS.HIWORD (oneItem) - OS.HIWORD (empty);
     } else {
         struct_.itemHeight = itemHeight;
     }
@@ -5681,196 +6184,17 @@
 }
 
 override LRESULT wmNotify (NMHDR* hdr, int wParam, int lParam) {
-    auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
+    HWND hwndToolTip = cast(HWND) OS.SendMessage (handle, OS.LVM_GETTOOLTIPS, 0, 0);
+    if (hdr.hwndFrom is hwndToolTip) {
+        LRESULT result = wmNotifyToolTip (hdr, wParam, lParam);
+        if (result !is null) return result;
+    }
+    HWND hwndHeader = cast(HWND)OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0);
     if (hdr.hwndFrom is hwndHeader) {
-        /*
-        * Feature in Windows.  On NT, the automatically created
-        * header control is created as a UNICODE window, not an
-        * ANSI window despite the fact that the parent is created
-        * as an ANSI window.  This means that it sends UNICODE
-        * notification messages to the parent window on NT for
-        * no good reason.  The data and size in the NMHEADER and
-        * HDITEM structs is identical between the platforms so no
-        * different message is actually necessary.  Despite this,
-        * Windows sends different messages.  The fix is to look
-        * for both messages, despite the platform.  This works
-        * because only one will be sent on either platform, never
-        * both.
-        */
-        switch (hdr.code) {
-            case OS.HDN_BEGINTRACKW:
-            case OS.HDN_BEGINTRACKA:
-            case OS.HDN_DIVIDERDBLCLICKW:
-            case OS.HDN_DIVIDERDBLCLICKA: {
-                if (columnCount is 0) return LRESULT.ONE;
-                NMHEADER* phdn = cast(NMHEADER*)lParam;
-                //OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
-                TableColumn column = columns [phdn.iItem];
-                if (column !is null && !column.getResizable ()) {
-                    return LRESULT.ONE;
-                }
-                ignoreColumnMove = true;
-                switch (hdr.code) {
-                    case OS.HDN_DIVIDERDBLCLICKW:
-                    case OS.HDN_DIVIDERDBLCLICKA:
-                        /*
-                        * Bug in Windows.  When the first column of a table does not
-                        * have an image and the user double clicks on the divider,
-                        * Windows packs the column but does not take into account
-                        * the empty space left for the image.  The fix is to measure
-                        * each items ourselves rather than letting Windows do it.
-                        */
-                        bool fixPack = phdn.iItem is 0 && !firstColumnImage;
-                        if (column !is null && (fixPack || hooks (DWT.MeasureItem))) {
-                            column.pack ();
-                            return LRESULT.ONE;
-                        }
-                    default:
-                }
-                break;
-            }
-            case OS.NM_RELEASEDCAPTURE: {
-                if (!ignoreColumnMove) {
-                    for (int i=0; i<columnCount; i++) {
-                        TableColumn column = columns [i];
-                        column.updateToolTip (i);
-                    }
-                }
-                ignoreColumnMove = false;
-                break;
-            }
-            case OS.HDN_BEGINDRAG: {
-                if (ignoreColumnMove) return LRESULT.ONE;
-                int bits = OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
-                if ((bits & OS.LVS_EX_HEADERDRAGDROP) is 0) break;
-                if (columnCount is 0) return LRESULT.ONE;
-                NMHEADER* phdn = cast(NMHEADER*)lParam;
-                //OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
-                if (phdn.iItem !is -1) {
-                    TableColumn column = columns [phdn.iItem];
-                    if (column !is null && !column.getMoveable ()) {
-                        ignoreColumnMove = true;
-                        return LRESULT.ONE;
-                    }
-                }
-                break;
-            }
-            case OS.HDN_ENDDRAG: {
-                int bits = OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
-                if ((bits & OS.LVS_EX_HEADERDRAGDROP) is 0) break;
-                NMHEADER* phdn = cast(NMHEADER*)lParam;
-                //OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
-                if (phdn.iItem !is -1 && phdn.pitem !is null) {
-                    HDITEM* pitem = cast(HDITEM*)phdn.pitem;
-                    //OS.MoveMemory (pitem, phdn.pitem, HDITEM.sizeof);
-                    if ((pitem.mask & OS.HDI_ORDER) !is 0 && pitem.iOrder !is -1) {
-                        if (columnCount is 0) break;
-                        int [] order = new int [columnCount];
-                        OS.SendMessage (handle, OS.LVM_GETCOLUMNORDERARRAY, columnCount, order.ptr);
-                        int index = 0;
-                        while (index < order.length) {
-                            if (order [index] is phdn.iItem) break;
-                            index++;
-                        }
-                        if (index is order.length) index = 0;
-                        if (index is pitem.iOrder) break;
-                        int start = Math.min (index, pitem.iOrder);
-                        int end = Math.max (index, pitem.iOrder);
-                        ignoreColumnMove = false;
-                        for (int i=start; i<=end; i++) {
-                            TableColumn column = columns [order [i]];
-                            if (!column.isDisposed ()) {
-                                column.postEvent (DWT.Move);
-                            }
-                        }
-                    }
-                }
-                break;
-            }
-            case OS.HDN_ITEMCHANGEDW:
-            case OS.HDN_ITEMCHANGEDA: {
-                /*
-                * Bug in Windows.  When a table has the LVS_EX_GRIDLINES extended
-                * style and the user drags any column over the first column in the
-                * table, making the size become zero, when the user drags a column
-                * such that the size of the first column becomes non-zero, the grid
-                * lines are not redrawn.  The fix is to detect the case and force
-                * a redraw of the first column.
-                */
-                int width = OS.SendMessage (handle, OS.LVM_GETCOLUMNWIDTH, 0, 0);
-                if (lastWidth is 0 && width > 0) {
-                    int bits = OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
-                    if ((bits & OS.LVS_EX_GRIDLINES) !is 0) {
-                        RECT rect;
-                        OS.GetClientRect (handle, &rect);
-                        rect.right = rect.left + width;
-                        OS.InvalidateRect (handle, &rect, true);
-                    }
-                }
-                lastWidth = width;
-                if (!ignoreColumnResize) {
-                    NMHEADER* phdn = cast(NMHEADER*)lParam;
-                    //OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
-                    if (phdn.pitem !is null) {
-                        HDITEM* pitem = cast(HDITEM*)phdn.pitem;
-                        //OS.MoveMemory (pitem, phdn.pitem, HDITEM.sizeof);
-                        if ((pitem.mask & OS.HDI_WIDTH) !is 0) {
-                            TableColumn column = columns [phdn.iItem];
-                            if (column !is null) {
-                                column.updateToolTip (phdn.iItem);
-                                column.sendEvent (DWT.Resize);
-                                if (isDisposed ()) return LRESULT.ZERO;
-                                /*
-                                * It is possible (but unlikely), that application
-                                * code could have disposed the column in the move
-                                * event.  If this happens, process the move event
-                                * for those columns that have not been destroyed.
-                                */
-                                TableColumn [] newColumns = new TableColumn [columnCount];
-                                System.arraycopy (columns, 0, newColumns, 0, columnCount);
-                                int [] order = new int [columnCount];
-                                OS.SendMessage (handle, OS.LVM_GETCOLUMNORDERARRAY, columnCount, order.ptr);
-                                bool moved = false;
-                                for (int i=0; i<columnCount; i++) {
-                                    TableColumn nextColumn = newColumns [order [i]];
-                                    if (moved && !nextColumn.isDisposed ()) {
-                                        nextColumn.updateToolTip (order [i]);
-                                        nextColumn.sendEvent (DWT.Move);
-                                    }
-                                    if (nextColumn is column) moved = true;
-                                }
-                            }
-                        }
-                    }
-                }
-                break;
-            }
-            case OS.HDN_ITEMDBLCLICKW:
-            case OS.HDN_ITEMDBLCLICKA: {
-                NMHEADER* phdn = cast(NMHEADER*)lParam;
-                //OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
-                TableColumn column = columns [phdn.iItem];
-                if (column !is null) {
-                    column.postEvent (DWT.DefaultSelection);
-                }
-                break;
-            }
-            default:
-        }
-    }
-    LRESULT result = super.wmNotify (hdr, wParam, lParam);
-    if (result !is null) return result;
-    switch (hdr.code) {
-        case OS.TTN_GETDISPINFOA:
-        case OS.TTN_GETDISPINFOW: {
-            tipRequested = true;
-            int code = callWindowProc (handle, OS.WM_NOTIFY, wParam, lParam);
-            tipRequested = false;
-            return new LRESULT (code);
-        }
-        default:
-    }
-    return result;
+        LRESULT result = wmNotifyHeader (hdr, wParam, lParam);
+        if (result !is null) return result;
+    }
+    return super.wmNotify (hdr, wParam, lParam);
 }
 
 override LRESULT wmNotifyChild (NMHDR* hdr, int wParam, int lParam) {
@@ -5898,6 +6222,11 @@
             NMLVDISPINFO* plvfi = cast(NMLVDISPINFO*)lParam;
             //OS.MoveMemory (plvfi, lParam, NMLVDISPINFO.sizeof);
 
+            bool [] visible = display.columnVisible;
+            if (visible !is null && !visible [plvfi.item.iSubItem]) {
+                break;
+            }
+
             /*
             * When an item is being deleted from a virtual table, do not
             * allow the application to provide data for a new item that
@@ -6056,16 +6385,19 @@
             if (hooks (DWT.MouseDown) || hooks (DWT.MouseUp)) {
                 return LRESULT.ONE;
             }
+            if ((style & DWT.RIGHT_TO_LEFT) !is 0) {
+                if (findImageControl () !is null) return LRESULT.ONE;
+            }
             break;
         }
         case OS.LVN_BEGINDRAG:
         case OS.LVN_BEGINRDRAG: {
+            if (OS.GetKeyState (OS.VK_LBUTTON) >= 0) break;
             dragStarted = true;
             if (hdr.code is OS.LVN_BEGINDRAG) {
                 int pos = OS.GetMessagePos ();
                 POINT pt;
-                pt.x = cast(short) (pos & 0xFFFF);
-                pt.y = cast(short) (pos >> 16);
+                OS.POINTSTOPOINT (pt, pos);
                 OS.ScreenToClient (handle, &pt);
                 sendDragEvent (1, pt.x, pt.y);
             }
@@ -6092,6 +6424,11 @@
             break;
         }
         case OS.LVN_ITEMCHANGED: {
+            if (fullRowSelect) {
+                fullRowSelect = false;
+                OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+                OS.SendMessage (handle, OS.LVM_SETEXTENDEDLISTVIEWSTYLE, OS.LVS_EX_FULLROWSELECT, 0);
+            }
             if (!ignoreSelect) {
                 NMLISTVIEW* pnmlv = cast(NMLISTVIEW*)lParam;
                 //OS.MoveMemory (pnmlv, lParam, NMLISTVIEW.sizeof);
@@ -6164,5 +6501,365 @@
     return super.wmNotifyChild (hdr, wParam, lParam);
 }
 
-}
-
+LRESULT wmNotifyHeader (NMHDR* hdr, int /*long*/ wParam, int /*long*/ lParam) {
+    /*
+    * Feature in Windows.  On NT, the automatically created
+    * header control is created as a UNICODE window, not an
+    * ANSI window despite the fact that the parent is created
+    * as an ANSI window.  This means that it sends UNICODE
+    * notification messages to the parent window on NT for
+    * no good reason.  The data and size in the NMHEADER and
+    * HDITEM structs is identical between the platforms so no
+    * different message is actually necessary.  Despite this,
+    * Windows sends different messages.  The fix is to look
+    * for both messages, despite the platform.  This works
+    * because only one will be sent on either platform, never
+    * both.
+    */
+    switch (hdr.code) {
+        case OS.HDN_BEGINTRACKW:
+        case OS.HDN_BEGINTRACKA:
+        case OS.HDN_DIVIDERDBLCLICKW:
+        case OS.HDN_DIVIDERDBLCLICKA: {
+            if (columnCount is 0) return LRESULT.ONE;
+            NMHEADER* phdn = cast(NMHEADER*)lParam;
+            TableColumn column = columns [phdn.iItem];
+            if (column !is null && !column.getResizable ()) {
+                return LRESULT.ONE;
+            }
+            ignoreColumnMove = true;
+            switch (hdr.code) {
+                case OS.HDN_DIVIDERDBLCLICKW:
+                case OS.HDN_DIVIDERDBLCLICKA:
+                    /*
+                    * Bug in Windows.  When the first column of a table does not
+                    * have an image and the user double clicks on the divider,
+                    * Windows packs the column but does not take into account
+                    * the empty space left for the image.  The fix is to measure
+                    * each items ourselves rather than letting Windows do it.
+                    */
+                    bool fixPack = phdn.iItem is 0 && !firstColumnImage;
+                    if (column !is null && (fixPack || hooks (DWT.MeasureItem))) {
+                        column.pack ();
+                        return LRESULT.ONE;
+                    }
+                default:
+            }
+            break;
+        }
+        case OS.NM_RELEASEDCAPTURE: {
+            if (!ignoreColumnMove) {
+                for (int i=0; i<columnCount; i++) {
+                    TableColumn column = columns [i];
+                    column.updateToolTip (i);
+                }
+            }
+            ignoreColumnMove = false;
+            break;
+        }
+        case OS.HDN_BEGINDRAG: {
+            if (ignoreColumnMove) return LRESULT.ONE;
+            int bits = OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
+            if ((bits & OS.LVS_EX_HEADERDRAGDROP) is 0) break;
+            if (columnCount is 0) return LRESULT.ONE;
+            NMHEADER* phdn = cast(NMHEADER*)lParam;
+            if (phdn.iItem !is -1) {
+                TableColumn column = columns [phdn.iItem];
+                if (column !is null && !column.getMoveable ()) {
+                    ignoreColumnMove = true;
+                    return LRESULT.ONE;
+                }
+            }
+            break;
+        }
+        case OS.HDN_ENDDRAG: {
+            int bits = OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
+            if ((bits & OS.LVS_EX_HEADERDRAGDROP) is 0) break;
+            NMHEADER* phdn = cast(NMHEADER*)lParam;
+            if (cast(int)phdn.iItem !is -1 && cast(int)phdn.pitem !is 0) {
+                HDITEM* pitem = cast(HDITEM*)phdn.pitem;
+                if ((pitem.mask & OS.HDI_ORDER) !is 0 && pitem.iOrder !is -1) {
+                    if (columnCount is 0) break;
+                    int [] order = new int [columnCount];
+                    OS.SendMessage (handle, OS.LVM_GETCOLUMNORDERARRAY, columnCount, order.ptr);
+                    int index = 0;
+                    while (index < order.length) {
+                        if (order [index] is phdn.iItem) break;
+                        index++;
+                    }
+                    if (index is order.length) index = 0;
+                    if (index is pitem.iOrder) break;
+                    int start = Math.min (index, pitem.iOrder);
+                    int end = Math.max (index, pitem.iOrder);
+                    ignoreColumnMove = false;
+                    for (int i=start; i<=end; i++) {
+                        TableColumn column = columns [order [i]];
+                        if (!column.isDisposed ()) {
+                            column.postEvent (DWT.Move);
+                        }
+                    }
+                }
+            }
+            break;
+        }
+        case OS.HDN_ITEMCHANGEDW:
+        case OS.HDN_ITEMCHANGEDA: {
+            /*
+            * Bug in Windows.  When a table has the LVS_EX_GRIDLINES extended
+            * style and the user drags any column over the first column in the
+            * table, making the size become zero, when the user drags a column
+            * such that the size of the first column becomes non-zero, the grid
+            * lines are not redrawn.  The fix is to detect the case and force
+            * a redraw of the first column.
+            */
+            int width = OS.SendMessage (handle, OS.LVM_GETCOLUMNWIDTH, 0, 0);
+            if (lastWidth is 0 && width > 0) {
+                int bits = OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
+                if ((bits & OS.LVS_EX_GRIDLINES) !is 0) {
+                    RECT rect;
+                    OS.GetClientRect (handle, &rect);
+                    rect.right = rect.left + width;
+                    OS.InvalidateRect (handle, &rect, true);
+                }
+            }
+            lastWidth = width;
+            if (!ignoreColumnResize) {
+                NMHEADER* phdn = cast(NMHEADER*)lParam;
+                if (phdn.pitem !is null) {
+                    HDITEM* pitem = cast(HDITEM*)phdn.pitem;
+                    if ((pitem.mask & OS.HDI_WIDTH) !is 0) {
+                        TableColumn column = columns [phdn.iItem];
+                        if (column !is null) {
+                            column.updateToolTip (phdn.iItem);
+                            column.sendEvent (DWT.Resize);
+                            if (isDisposed ()) return LRESULT.ZERO;
+                            /*
+                            * It is possible (but unlikely), that application
+                            * code could have disposed the column in the move
+                            * event.  If this happens, process the move event
+                            * for those columns that have not been destroyed.
+                            */
+                            TableColumn [] newColumns = new TableColumn [columnCount];
+                            System.arraycopy (columns, 0, newColumns, 0, columnCount);
+                            int [] order = new int [columnCount];
+                            OS.SendMessage (handle, OS.LVM_GETCOLUMNORDERARRAY, columnCount, order.ptr);
+                            bool moved = false;
+                            for (int i=0; i<columnCount; i++) {
+                                TableColumn nextColumn = newColumns [order [i]];
+                                if (moved && !nextColumn.isDisposed ()) {
+                                    nextColumn.updateToolTip (order [i]);
+                                    nextColumn.sendEvent (DWT.Move);
+                                }
+                                if (nextColumn is column) moved = true;
+                            }
+                        }
+                    }
+                }
+            }
+            break;
+        }
+        case OS.HDN_ITEMDBLCLICKW:
+        case OS.HDN_ITEMDBLCLICKA: {
+            NMHEADER* phdn = cast(NMHEADER*)lParam;
+            TableColumn column = columns [phdn.iItem];
+            if (column !is null) {
+                column.postEvent (DWT.DefaultSelection);
+            }
+            break;
+        }
+        default:
+    }
+    return null;
+}
+
+LRESULT wmNotifyToolTip (NMHDR* hdr, int /*long*/ wParam, int /*long*/ lParam) {
+    if (OS.IsWinCE) return null;
+    switch (hdr.code) {
+        case OS.NM_CUSTOMDRAW: {
+            if (toolTipText_ !is null) break;
+            if (isCustomToolTip ()) {
+                NMTTCUSTOMDRAW* nmcd = cast(NMTTCUSTOMDRAW*)lParam;
+                return wmNotifyToolTip (nmcd, lParam);
+            }
+            break;
+        }
+        case OS.TTN_GETDISPINFOA:
+        case OS.TTN_GETDISPINFOW:
+        case OS.TTN_SHOW: {
+            LRESULT result = super.wmNotify (hdr, wParam, lParam);
+            if (result !is null) return result;
+            if (hdr.code !is OS.TTN_SHOW) tipRequested = true;
+            int /*long*/ code = callWindowProc (handle, OS.WM_NOTIFY, wParam, lParam);
+            if (hdr.code !is OS.TTN_SHOW) tipRequested = false;
+            if (toolTipText_ !is null) break;
+            if (isCustomToolTip ()) {
+                LVHITTESTINFO pinfo;
+                int pos = OS.GetMessagePos ();
+                POINT pt;
+                OS.POINTSTOPOINT (pt, pos);
+                OS.ScreenToClient (handle, &pt);
+                pinfo.pt.x = pt.x;
+                pinfo.pt.y = pt.y;
+                if (OS.SendMessage (handle, OS.LVM_SUBITEMHITTEST, 0, &pinfo) !is -1) {
+                    TableItem item = _getItem (pinfo.iItem);
+                    auto hDC = OS.GetDC (handle);
+                    HFONT oldFont, newFont = cast(HFONT)OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+                    if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
+                    auto hFont = item.fontHandle (pinfo.iSubItem);
+                    if (cast(int)hFont !is -1) hFont = cast(HFONT)OS.SelectObject (hDC, hFont);
+                    Event event = sendMeasureItemEvent (item, pinfo.iItem, pinfo.iSubItem, hDC);
+                    if (!isDisposed () && !item.isDisposed ()) {
+                        RECT itemRect;
+                        OS.SetRect (&itemRect, event.x, event.y, event.x + event.width, event.y + event.height);
+                        if (hdr.code is OS.TTN_SHOW) {
+                            RECT* toolRect = toolTipRect (&itemRect);
+                            OS.MapWindowPoints (handle, null, cast(POINT*)toolRect, 2);
+                            auto hwndToolTip = cast(HWND) OS.SendMessage (handle, OS.LVM_GETTOOLTIPS, 0, 0);
+                            int flags = OS.SWP_NOACTIVATE | OS.SWP_NOZORDER;
+                            int width = toolRect.right - toolRect.left, height = toolRect.bottom - toolRect.top;
+                            SetWindowPos (hwndToolTip, null, toolRect.left , toolRect.top, width, height, flags);
+                        } else {
+                            NMTTDISPINFO* lpnmtdi = null;
+                            if (hdr.code is OS.TTN_GETDISPINFOA) {
+                                lpnmtdi = cast(NMTTDISPINFO*)new NMTTDISPINFOA;
+                                OS.MoveMemory (lpnmtdi, cast(void*) lParam, NMTTDISPINFOA.sizeof);
+                                if (lpnmtdi.lpszText !is null) {
+                                    (cast(char*)lpnmtdi.lpszText)[0] = 0;
+                                }
+                            } else {
+                                lpnmtdi = cast(NMTTDISPINFO*)new NMTTDISPINFOW;
+                                OS.MoveMemory (lpnmtdi, cast(void*) lParam, NMTTDISPINFOW.sizeof);
+                                if (lpnmtdi.lpszText !is null) {
+                                    (cast(wchar*)lpnmtdi.lpszText)[0] = 0;
+                                }
+                            }
+                            RECT cellRect = item.getBounds (pinfo.iItem, pinfo.iSubItem, true, true, true, true, hDC);
+                            if (itemRect.right > cellRect.right) {
+                                //TEMPORARY CODE
+                                String string = " ";
+//                              String string = null;
+//                              if (pinfo.iSubItem is 0) {
+//                                  string = item.text;
+//                              } else {
+//                                  String [] strings  = item.strings;
+//                                  if (strings !is null) string = strings [pinfo.iSubItem];
+//                              }
+                                if (string !is null) {
+                                    Shell shell = getShell ();
+                                    wchar [] chars = StrToTCHARs(string, true );
+                                    if (hdr.code is OS.TTN_GETDISPINFOA) {
+                                        char [] bytes = new char [chars.length * 2];
+                                        OS.WideCharToMultiByte (getCodePage (), 0, chars.ptr, chars.length, bytes.ptr, bytes.length, null, null);
+                                        shell.setToolTipText (lpnmtdi, bytes);
+                                        OS.MoveMemory (lParam, cast(NMTTDISPINFOA*)lpnmtdi, NMTTDISPINFOA.sizeof);
+                                    } else {
+                                        shell.setToolTipText (lpnmtdi, chars);
+                                        OS.MoveMemory (lParam, cast(NMTTDISPINFOW*)lpnmtdi, NMTTDISPINFOW.sizeof);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                    if (hFont !is cast(HFONT)-1) hFont = OS.SelectObject (hDC, hFont);
+                    if (newFont !is null) OS.SelectObject (hDC, oldFont);
+                    OS.ReleaseDC (handle, hDC);
+                }
+            }
+            return new LRESULT (code);
+        }
+    }
+    return null;
+}
+
+LRESULT wmNotifyToolTip (NMTTCUSTOMDRAW* nmcd, int /*long*/ lParam) {
+    if (OS.IsWinCE) return null;
+    switch (nmcd.nmcd.dwDrawStage) {
+        case OS.CDDS_PREPAINT: {
+            if (isCustomToolTip ()) {
+                //TEMPORARY CODE
+//              nmcd.uDrawFlags |= OS.DT_CALCRECT;
+//              OS.MoveMemory (lParam, nmcd, NMTTCUSTOMDRAW.sizeof);
+                return new LRESULT (OS.CDRF_NOTIFYPOSTPAINT | OS.CDRF_NEWFONT);
+            }
+            break;
+        }
+        case OS.CDDS_POSTPAINT: {
+            LVHITTESTINFO pinfo;
+            int pos = OS.GetMessagePos ();
+            POINT pt;
+            OS.POINTSTOPOINT (pt, pos);
+            OS.ScreenToClient (handle, &pt);
+            pinfo.pt.x = pt.x;
+            pinfo.pt.y = pt.y;
+            if (OS.SendMessage (handle, OS.LVM_SUBITEMHITTEST, 0, &pinfo) !is -1) {
+                TableItem item = _getItem (pinfo.iItem);
+                auto hDC = OS.GetDC (handle);
+                auto hFont = item.fontHandle (pinfo.iSubItem);
+                if (cast(int)hFont is -1) hFont = cast(HFONT)OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+                auto oldFont = cast(HFONT)OS.SelectObject (hDC, hFont);
+                bool drawForeground = true;
+                RECT cellRect = item.getBounds (pinfo.iItem, pinfo.iSubItem, true, true, false, false, hDC);
+                if (hooks (DWT.EraseItem)) {
+                    Event event = sendEraseItemEvent (item, nmcd, pinfo.iSubItem, &cellRect);
+                    if (isDisposed () || item.isDisposed ()) break;
+                    if (event.doit) {
+                        drawForeground = (event.detail & DWT.FOREGROUND) !is 0;
+                    } else {
+                        drawForeground = false;
+                    }
+                }
+                if (drawForeground) {
+                    int nSavedDC = OS.SaveDC (nmcd.nmcd.hdc);
+                    int gridWidth = getLinesVisible () ? Table.GRID_WIDTH : 0;
+                    RECT* insetRect = toolTipInset (&cellRect);
+                    OS.SetWindowOrgEx (nmcd.nmcd.hdc, insetRect.left, insetRect.top, null);
+                    GCData data = new GCData ();
+                    data.device = display;
+                    data.foreground = OS.GetTextColor (nmcd.nmcd.hdc);
+                    data.background = OS.GetBkColor (nmcd.nmcd.hdc);
+                    data.font = Font.win32_new (display, hFont);
+                    GC gc = GC.win32_new (nmcd.nmcd.hdc, data);
+                    int x = cellRect.left;
+                    if (pinfo.iSubItem !is 0) x -= gridWidth;
+                    Image image = item.getImage (pinfo.iSubItem);
+                    if (image !is null) {
+                        Rectangle rect = image.getBounds ();
+                        RECT imageRect = item.getBounds (pinfo.iItem, pinfo.iSubItem, false, true, false, false, hDC);
+                        Point size = imageList is null ? new Point (rect.width, rect.height) : imageList.getImageSize ();
+                        int y = imageRect.top;
+                        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+                            y = y + Math.max (0, (imageRect.bottom - imageRect.top - size.y) / 2);
+                        }
+                        gc.drawImage (image, rect.x, rect.y, rect.width, rect.height, x, y, size.x, size.y);
+                        x += size.x + INSET + (pinfo.iSubItem is 0 ? -2 : 4);
+                    } else {
+                        x += INSET + 2;
+                    }
+                    String string = item.getText (pinfo.iSubItem);
+                    if (string !is null) {
+                        int flags = OS.DT_NOPREFIX | OS.DT_SINGLELINE | OS.DT_VCENTER;
+                        TableColumn column = columns !is null ? columns [pinfo.iSubItem] : null;
+                        if (column !is null) {
+                            if ((column.style & DWT.CENTER) !is 0) flags |= OS.DT_CENTER;
+                            if ((column.style & DWT.RIGHT) !is 0) flags |= OS.DT_RIGHT;
+                        }
+                        TCHAR[] buffer = StrToTCHARs (getCodePage (), string, false);
+                        RECT textRect;
+                        OS.SetRect (&textRect, x, cellRect.top, cellRect.right, cellRect.bottom);
+                        OS.DrawText (nmcd.nmcd.hdc, buffer.ptr, buffer.length, &textRect, flags);
+                    }
+                    gc.dispose ();
+                    OS.RestoreDC (nmcd.nmcd.hdc, nSavedDC);
+                }
+                if (hooks (DWT.PaintItem)) {
+                    RECT itemRect = item.getBounds (pinfo.iItem, pinfo.iSubItem, true, true, false, false, hDC);
+                    sendPaintItemEvent (item, nmcd, pinfo.iSubItem, &itemRect);
+                }
+                OS.SelectObject (hDC, oldFont);
+                OS.ReleaseDC (handle, hDC);
+            }
+        }
+    }
+    return null;
+}
+}
--- a/dwt/widgets/TableColumn.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/TableColumn.d	Sat May 17 17:34:28 2008 +0200
@@ -104,7 +104,10 @@
  * lists the style constants that are applicable to the class.
  * Style bits are also inherited from superclasses.
  * </p>
- *
+ * <p>
+ * Note that due to a restriction on some platforms, the first column
+ * is always left aligned.
+ * </p>
  * @param parent a composite control which will be the parent of the new instance (cannot be null)
  * @param style the style of control to construct
  * @param index the zero-relative index to store the receiver in its parent
@@ -387,8 +390,7 @@
         for (int i=0; i<count; i++) {
             TableItem item = parent.items [i];
             if (item !is null) {
-                auto hFont = item.cellFont !is null ? item.cellFont [index] : cast(HFONT)-1;
-                if (hFont is cast(HFONT)-1) hFont = item.font;
+                auto hFont = item.fontHandle (index);
                 if (hFont !is cast(HFONT)-1) hFont = OS.SelectObject (hDC, hFont);
                 Event event = parent.sendMeasureItemEvent (item, i, index, hDC);
                 if (hFont !is cast(HFONT)-1) hFont = OS.SelectObject (hDC, hFont);
@@ -544,7 +546,10 @@
  * Controls how text and images will be displayed in the receiver.
  * The argument should be one of <code>LEFT</code>, <code>RIGHT</code>
  * or <code>CENTER</code>.
- *
+ * <p>
+ * Note that due to a restriction on some platforms, the first column
+ * is always left aligned.
+ * </p>
  * @param alignment the new alignment
  *
  * @exception DWTException <ul>
@@ -702,10 +707,12 @@
             case DWT.UP:
                 hdItem.fmt &= ~(OS.HDF_IMAGE | OS.HDF_SORTDOWN);
                 hdItem.fmt |= OS.HDF_SORTUP;
+                if (image is null) hdItem.mask &= ~OS.HDI_IMAGE;
                 break;
             case DWT.DOWN:
                 hdItem.fmt &= ~(OS.HDF_IMAGE | OS.HDF_SORTUP);
                 hdItem.fmt |= OS.HDF_SORTDOWN;
+                if (image is null) hdItem.mask &= ~OS.HDI_IMAGE;
                 break;
             case DWT.NONE:
                 hdItem.fmt &= ~(OS.HDF_SORTUP | OS.HDF_SORTDOWN);
@@ -800,7 +807,7 @@
     * with spaces.
     */
     auto hHeap = OS.GetProcessHeap ();
-    TCHAR[] buffer = StrToTCHARs (parent.getCodePage (), fixMnemonic (string), true);
+    TCHAR[] buffer = StrToTCHARs (parent.getCodePage (), fixMnemonic (string, true), true);
     int byteCount = buffer.length * TCHAR.sizeof;
     auto pszText = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
     OS.MoveMemory (pszText, buffer.ptr, byteCount);
--- a/dwt/widgets/TableItem.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/TableItem.d	Sat May 17 17:34:28 2008 +0200
@@ -45,11 +45,11 @@
     Table parent;
     String [] strings;
     Image [] images;
+    Font font;
+    Font [] cellFont;
     bool checked, grayed, cached;
     int imageIndent, background = -1, foreground = -1;
-    HFONT font = cast(HFONT)-1;
     int [] cellBackground, cellForeground;
-    HFONT[] cellFont;
 
 /**
  * Constructs a new instance of this class given its parent
@@ -143,8 +143,9 @@
     images = null;
     imageIndent = 0;
     checked = grayed = false;
+    font = null;
     background = foreground = -1;
-    font = cast(HFONT)-1;
+    cellFont = null;
     cellBackground = cellForeground = null;
     cellFont = null;
     if ((parent.style & DWT.VIRTUAL) !is 0) cached = false;
@@ -155,6 +156,12 @@
     releaseHandle ();
 }
 
+HFONT fontHandle (int index) {
+    if (cellFont !is null && cellFont [index] !is null) return cellFont [index].handle;
+    if (font !is null) return font.handle;
+    return cast(HFONT)-1;
+}
+
 /**
  * Returns the receiver's background color.
  *
@@ -264,8 +271,7 @@
             if (code is 0) return RECT.init;
             if (getText) {
                 int width = 0;
-                auto hFont = cellFont !is null ? cellFont [column] : cast(HFONT)-1;
-                if (hFont is cast(HFONT)-1) hFont = font;
+                auto hFont = fontHandle (column);
                 if (hFont is cast(HFONT)-1 && hDC is null) {
                     TCHAR* buffer = StrToTCHARz (parent.getCodePage (), text);
                     width = OS.SendMessage (hwnd, OS.LVM_GETSTRINGWIDTH, 0, buffer);
@@ -444,7 +450,7 @@
 public Font getFont () {
     checkWidget ();
     if (!parent.checkData (this, true)) error (DWT.ERROR_WIDGET_DISPOSED);
-    return font is cast(HFONT)-1 ? parent.getFont () : Font.win32_new (display, font);
+    return font !is null ? font : parent.getFont ();
 }
 
 /**
@@ -466,8 +472,8 @@
     if (!parent.checkData (this, true)) error (DWT.ERROR_WIDGET_DISPOSED);
     int count = Math.max (1, parent.getColumnCount ());
     if (0 > index || index > count -1) return getFont ();
-    auto hFont = (cellFont !is null) ? cellFont [index] : font;
-    return hFont is cast(HFONT)-1 ? getFont () : Font.win32_new (display, hFont);
+    if (cellFont is null || cellFont [index] is null) return getFont ();
+    return cellFont [index];
 }
 
 /**
@@ -711,8 +717,8 @@
     super.releaseWidget ();
     strings = null;
     images = null;
+    cellFont = null;
     cellBackground = cellForeground = null;
-    cellFont = null;
 }
 
 /**
@@ -842,13 +848,11 @@
     if (font !is null && font.isDisposed ()) {
         DWT.error (DWT.ERROR_INVALID_ARGUMENT);
     }
-    HFONT hFont = cast(HFONT)-1;
-    if (font !is null) {
-        parent.setCustomDraw (true);
-        hFont = font.handle;
-    }
-    if (this.font is hFont) return;
-    this.font = hFont;
+    Font oldFont = this.font;
+    if (oldFont is font) return;
+    this.font = font;
+    if (oldFont !is null && oldFont.opEquals (font)) return;
+    if (font !is null) parent.setCustomDraw (true);
     if ((parent.style & DWT.VIRTUAL) !is 0) cached = true;
     /*
     * Bug in Windows.  Despite the fact that every item in the
@@ -903,19 +907,15 @@
     }
     int count = Math.max (1, parent.getColumnCount ());
     if (0 > index || index > count - 1) return;
-    auto hFont = cast(HFONT)-1;
-    if (font !is null) {
-        parent.setCustomDraw (true);
-        hFont = font.handle;
+    if (cellFont is null) {
+        if (font is null) return;
+        cellFont = new Font [count];
     }
-    if (cellFont is null) {
-        cellFont = new HFONT [count];
-        for (int i = 0; i < count; i++) {
-            cellFont [i] = cast(HFONT)-1;
-        }
-    }
-    if (cellFont [index] is hFont) return;
-    cellFont [index] = hFont;
+    Font oldFont = cellFont [index];
+    if (oldFont is font) return;
+    cellFont [index] = font;
+    if (oldFont !is null && oldFont.opEquals (font)) return;
+    if (font !is null) parent.setCustomDraw (true);
     if ((parent.style & DWT.VIRTUAL) !is 0) cached = true;
     if (index is 0) {
         /*
--- a/dwt/widgets/Text.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/Text.d	Sat May 17 17:34:28 2008 +0200
@@ -36,6 +36,13 @@
 /**
  * Instances of this class are selectable user interface
  * objects that allow the user to enter and modify text.
+ * Text controls can be either single or multi-line.
+ * When a text control is created with a border, the
+ * operating system includes a platform specific inset
+ * around the contents of the control.  When created
+ * without a border, an effort is made to remove the
+ * inset such that the preferred size of the control
+ * is the same size as the contents.
  * <p>
  * <dl>
  * <dt><b>Styles:</b></dt>
@@ -166,7 +173,60 @@
 
 override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) {
     if (handle is null) return 0;
-    return OS.CallWindowProc (EditProc, hwnd, msg, wParam, lParam);
+    bool redraw = false;
+    switch (msg) {
+        case OS.WM_ERASEBKGND: {
+            if (findImageControl () !is null) return 0;
+            break;
+        }
+        case OS.WM_HSCROLL:
+        case OS.WM_VSCROLL: {
+            redraw = findImageControl () !is null && drawCount is 0 && OS.IsWindowVisible (handle);
+            if (redraw) OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+            break;
+        }
+        case OS.WM_PAINT: {
+            if (findImageControl () !is null) {
+                PAINTSTRUCT ps;
+                auto paintDC = OS.BeginPaint (handle, &ps);
+                int width = ps.rcPaint.right - ps.rcPaint.left;
+                int height = ps.rcPaint.bottom - ps.rcPaint.top;
+                if (width !is 0 && height !is 0) {
+                    auto hDC = OS.CreateCompatibleDC (paintDC);
+                    POINT lpPoint1, lpPoint2;
+                    OS.SetWindowOrgEx (hDC, ps.rcPaint.left, ps.rcPaint.top, &lpPoint1);
+                    OS.SetBrushOrgEx (hDC, ps.rcPaint.left, ps.rcPaint.top, &lpPoint2);
+                    auto hBitmap = OS.CreateCompatibleBitmap (paintDC, width, height);
+                    auto hOldBitmap = OS.SelectObject (hDC, hBitmap);
+                    RECT rect;
+                    OS.SetRect (&rect, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom);
+                    drawBackground (hDC, &rect);
+                    OS.CallWindowProc ( EditProc, hwnd, OS.WM_PAINT, cast(int)hDC, lParam);
+                    OS.SetWindowOrgEx (hDC, lpPoint1.x, lpPoint1.y, null);
+                    OS.SetBrushOrgEx (hDC, lpPoint2.x, lpPoint2.y, null);
+                    OS.BitBlt (paintDC, ps.rcPaint.left, ps.rcPaint.top, width, height, hDC, 0, 0, OS.SRCCOPY);
+                    OS.SelectObject (hDC, hOldBitmap);
+                    OS.DeleteObject (hBitmap);
+                    OS.DeleteObject (hDC);
+                }
+                OS.EndPaint (handle, &ps);
+                return 0;
+            }
+            break;
+        }
+    }
+    int /*long*/ code = OS.CallWindowProc (EditProc, hwnd, msg, wParam, lParam);
+    switch (msg) {
+        case OS.WM_HSCROLL:
+        case OS.WM_VSCROLL: {
+            if (redraw) {
+                OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+                OS.InvalidateRect (handle, null, true);
+            }
+            break;
+        }
+    }
+    return code;
 }
 
 override void createHandle () {
@@ -420,9 +480,9 @@
     * the single-line text widget in an editable combo
     * box.
     */
-    int margins = OS.SendMessage(handle, OS.EM_GETMARGINS, 0, 0);
-    rect.x -= margins & 0xFFFF;
-    rect.width += (margins & 0xFFFF) + ((margins >> 16) & 0xFFFF);
+    int /*long*/ margins = OS.SendMessage(handle, OS.EM_GETMARGINS, 0, 0);
+    rect.x -= OS.LOWORD (margins);
+    rect.width += OS.LOWORD (margins) + OS.HIWORD (margins);
     if ((style & DWT.H_SCROLL) !is 0) rect.width++;
     if ((style & DWT.BORDER) !is 0) {
         rect.x -= 1;
@@ -485,8 +545,8 @@
         int start, end;
         OS.SendMessage (handle, OS.EM_GETSEL, &start, &end);
         if (start !is end ) {
-            int lParam = (x & 0xFFFF) | ((y << 16) & 0xFFFF0000);
-            int position = OS.SendMessage (handle, OS.EM_CHARFROMPOS, 0, lParam) & 0xFFFF;
+            int /*long*/ lParam = OS.MAKELPARAM (x, y);
+            int position = OS.LOWORD (OS.SendMessage (handle, OS.EM_CHARFROMPOS, 0, lParam));
             if (start <= position && position < end) {
                 if (super.dragDetect (hwnd, x, y, filter, detect, consume)) {
                     if (consume !is null) consume [0] = true;
@@ -612,7 +672,7 @@
     * pixel coordinates (0,0).
     */
     int position = getCaretPosition ();
-    int caretPos = OS.SendMessage (handle, OS.EM_POSFROMCHAR, position, 0);
+    int /*long*/ caretPos = OS.SendMessage (handle, OS.EM_POSFROMCHAR, position, 0);
     if (caretPos is -1) {
         caretPos = 0;
         if (position >= OS.GetWindowTextLength (handle)) {
@@ -641,7 +701,7 @@
             OS.SendMessage (handle, OS.EM_SETSEL, start , end );
         }
     }
-    return new Point (cast(short) (caretPos & 0xFFFF), cast(short) (caretPos >> 16));
+    return new Point (OS.GET_X_LPARAM (caretPos), OS.GET_Y_LPARAM (caretPos));
 }
 
 /**
@@ -902,8 +962,8 @@
 /*public*/ int getPosition (Point point) {
     checkWidget();
     if (point is null) error (DWT.ERROR_NULL_ARGUMENT);
-    int lParam = (point.x & 0xFFFF) | ((point.y << 16) & 0xFFFF0000);
-    int position = OS.SendMessage (handle, OS.EM_CHARFROMPOS, 0, lParam) & 0xFFFF;
+    int /*long*/ lParam = OS.MAKELPARAM (point.x, point.y);
+    int position = OS.LOWORD (OS.SendMessage (handle, OS.EM_CHARFROMPOS, 0, lParam));
     if (!OS.IsUnicode && OS.IsDBLocale) position = mbcsToWcsPos (position);
     return position;
 }
@@ -1465,8 +1525,8 @@
     if ((flags & OS.SWP_NOSIZE) is 0 && width !is 0) {
         RECT rect;
         OS.GetWindowRect (handle, &rect);
-        int margins = OS.SendMessage (handle, OS.EM_GETMARGINS, 0, 0);
-        int marginWidth = (margins & 0xFFFF) + ((margins >> 16) & 0xFFFF);
+        int /*long*/ margins = OS.SendMessage (handle, OS.EM_GETMARGINS, 0, 0);
+        int marginWidth = OS.LOWORD (margins) + OS.HIWORD (margins);
         if (rect.right - rect.left <= marginWidth) {
             int start, end;
             OS.SendMessage (handle, OS.EM_GETSEL, &start, &end);
@@ -1804,7 +1864,7 @@
     * to round off error, the tab spacing may not be the exact
     * number of space widths, depending on the font.
     */
-    int width = (getTabWidth (tabs) * 4) / (OS.GetDialogBaseUnits () & 0xFFFF);
+    int width = (getTabWidth (tabs) * 4) / OS.LOWORD (OS.GetDialogBaseUnits ());
     OS.SendMessage (handle, OS.EM_SETTABSTOPS, 1, &width);
 }
 
@@ -2151,7 +2211,7 @@
     * so DLGC_WANTARROWS should not be cleared.
     */
     if ((style & DWT.READ_ONLY) !is 0) {
-        int code = callWindowProc (handle, OS.WM_GETDLGCODE, wParam, lParam);
+        int /*long*/ code = callWindowProc (handle, OS.WM_GETDLGCODE, wParam, lParam);
         code &= ~(OS.DLGC_WANTALLKEYS | OS.DLGC_WANTTAB);
         return new LRESULT (code);
     }
@@ -2177,7 +2237,7 @@
     * them to the application.
     */
     ignoreCharacter = true;
-    int result = callWindowProc (handle, OS.WM_IME_CHAR, wParam, lParam);
+    int /*long*/ result = callWindowProc (handle, OS.WM_IME_CHAR, wParam, lParam);
     MSG msg;
     int flags = OS.PM_REMOVE | OS.PM_NOYIELD | OS.PM_QS_INPUT | OS.PM_QS_POSTMESSAGE;
     while (OS.PeekMessage (&msg, handle, OS.WM_CHAR, OS.WM_CHAR, flags)) {
@@ -2248,8 +2308,8 @@
         */
         bool hasMenu = menu !is null && !menu.isDisposed ();
         if (hasMenu || hooks (DWT.MenuDetect)) {
-            int x = cast(short) (lParam & 0xFFFF);
-            int y = cast(short) (lParam >> 16);
+            int x = OS.GET_X_LPARAM (lParam);
+            int y = OS.GET_Y_LPARAM (lParam);
             SHRGINFO shrg;
             shrg.cbSize = SHRGINFO.sizeof;
             shrg.hwndClient = handle;
@@ -2287,7 +2347,7 @@
     return wmClipboard (OS.WM_UNDO, wParam, lParam);
 }
 
-LRESULT wmClipboard (int msg, int wParam, int lParam) {
+LRESULT wmClipboard (int msg, int /*long*/ wParam, int /*long*/ lParam) {
     if ((style & DWT.READ_ONLY) !is 0) return null;
     if (!hooks (DWT.Verify) && !filters (DWT.Verify)) return null;
     bool call = false;
@@ -2390,9 +2450,12 @@
 }
 
 override LRESULT wmCommandChild (int wParam, int lParam) {
-    int code = wParam >> 16;
+    int code = OS.HIWORD (wParam);
     switch (code) {
         case OS.EN_CHANGE:
+            if (findImageControl () !is null) {
+                OS.InvalidateRect (handle, null, true);
+            }
             if (ignoreModify) break;
             /*
             * It is possible (but unlikely), that application
--- a/dwt/widgets/ToolBar.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/ToolBar.d	Sat May 17 17:34:28 2008 +0200
@@ -317,7 +317,7 @@
     * bar currently sets this value to 300 so it is not
     * necessary to set TTM_SETMAXTIPWIDTH.
     */
-//  int hwndToolTip = OS.SendMessage (handle, OS.TB_GETTOOLTIPS, 0, 0);
+//  int /*long*/ hwndToolTip = OS.SendMessage (handle, OS.TB_GETTOOLTIPS, 0, 0);
 //  OS.SendMessage (hwndToolTip, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF);
 
     /*
@@ -676,8 +676,8 @@
         TBBUTTONINFO info;
         info.cbSize = TBBUTTONINFO.sizeof;
         info.dwMask = OS.TBIF_SIZE;
-        int size = OS.SendMessage (handle, OS.TB_GETBUTTONSIZE, 0, 0);
-        info.cx = cast(short) (size & 0xFFFF);
+        int /*long*/ size = OS.SendMessage (handle, OS.TB_GETBUTTONSIZE, 0, 0);
+        info.cx = cast(short) OS.LOWORD (size);
         int index = 0;
         while (index < items.length) {
             ToolItem item = items [index];
@@ -685,8 +685,8 @@
             index++;
         }
         if (index < items.length) {
-            int padding = OS.SendMessage (handle, OS.TB_GETPADDING, 0, 0);
-            info.cx += (padding & 0xFFFF) * 2;
+            int /*long*/ padding = OS.SendMessage (handle, OS.TB_GETPADDING, 0, 0);
+            info.cx += OS.LOWORD (padding) * 2;
         }
         for (int i=0; i<items.length; i++) {
             ToolItem item = items [i];
@@ -974,7 +974,7 @@
         * choosing two instead of one as the row increment fixes both cases.
         */
         count += 2;
-        OS.SendMessage (handle, OS.TB_SETROWS, (1 << 16) | count, 0);
+        OS.SendMessage (handle, OS.TB_SETROWS, OS.MAKEWPARAM (count, 1), 0);
         int flags = OS.SWP_NOACTIVATE | OS.SWP_NOMOVE | OS.SWP_NOZORDER;
         SetWindowPos (handle, null, 0, 0, rect.right - rect.left, rect.bottom - rect.top, flags);
         ignoreResize = false;
@@ -1009,6 +1009,18 @@
     int index = hdr.hdr.idFrom;
     auto hwndToolTip = cast(HWND) OS.SendMessage (handle, OS.TB_GETTOOLTIPS, 0, 0);
     if (hwndToolTip is hdr.hdr.hwndFrom) {
+        /*
+        * Bug in Windows. For some reason the reading order
+        * in NMTTDISPINFO is sometimes set incorrectly.  The
+        * reading order seems to change every time the mouse
+        * enters the control from the top edge.  The fix is
+        * to explicitly set TTF_RTLREADING.
+        */
+        if ((style & DWT.RIGHT_TO_LEFT) !is 0) {
+            hdr.uFlags |= OS.TTF_RTLREADING;
+        } else {
+            hdr.uFlags &= ~OS.TTF_RTLREADING;
+        }
         if (toolTipText_ !is null) return ""; //$NON-NLS-1$
         if (0 <= index && index < items.length) {
             ToolItem item = items [index];
@@ -1240,7 +1252,7 @@
 
 override LRESULT WM_SIZE (int wParam, int lParam) {
     if (ignoreResize) {
-        int code = callWindowProc (handle, OS.WM_SIZE, wParam, lParam);
+        int /*long*/ code = callWindowProc (handle, OS.WM_SIZE, wParam, lParam);
         if (code is 0) return LRESULT.ZERO;
         return new LRESULT (code);
     }
@@ -1323,7 +1335,7 @@
 }
 
 override LRESULT wmCommandChild (int wParam, int lParam) {
-    ToolItem child = items [wParam & 0xFFFF];
+    ToolItem child = items [OS.LOWORD (wParam)];
     if (child is null) return null;
     return child.wmCommandChild (wParam, lParam);
 }
--- a/dwt/widgets/ToolItem.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/ToolItem.d	Sat May 17 17:34:28 2008 +0200
@@ -193,7 +193,7 @@
     * properly.
     */
     int y = rect.top + (rect.bottom - rect.top) / 2;
-    int lParam = ((dropDown ? rect.right - 1 : rect.left) & 0xFFFF) | ((y << 16) & 0xFFFF0000);
+    int /*long*/ lParam = OS.MAKELPARAM (dropDown ? rect.right - 1 : rect.left, y);
     parent.ignoreMouse = true;
     OS.SendMessage (hwnd, OS.WM_LBUTTONDOWN, 0, lParam);
     OS.SendMessage (hwnd, OS.WM_LBUTTONUP, 0, lParam);
@@ -287,7 +287,7 @@
         return (state & DISABLED) is 0;
     }
     auto hwnd = parent.handle;
-    int fsState = OS.SendMessage (hwnd, OS.TB_GETSTATE, id, 0);
+    int /*long*/ fsState = OS.SendMessage (hwnd, OS.TB_GETSTATE, id, 0);
     return (fsState & OS.TBSTATE_ENABLED) !is 0;
 }
 
@@ -346,7 +346,7 @@
     checkWidget();
     if ((style & (DWT.CHECK | DWT.RADIO)) is 0) return false;
     auto hwnd = parent.handle;
-    int fsState = OS.SendMessage (hwnd, OS.TB_GETSTATE, id, 0);
+    int /*long*/ fsState = OS.SendMessage (hwnd, OS.TB_GETSTATE, id, 0);
     return (fsState & OS.TBSTATE_CHECKED) !is 0;
 }
 
@@ -801,7 +801,7 @@
     * the tool bar to redraw and layout.
     */
     parent.setDropDownItems (false);
-    int hFont = OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0);
+    int /*long*/ hFont = OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0);
     OS.SendMessage (hwnd, OS.WM_SETFONT, hFont, 0);
     parent.setDropDownItems (true);
     parent.layoutItems ();
@@ -957,7 +957,7 @@
     return OS.BTNS_BUTTON;
 }
 
-LRESULT wmCommandChild (int wParam, int lParam) {
+LRESULT wmCommandChild (int /*long*/ wParam, int /*long*/ lParam) {
     if ((style & DWT.RADIO) !is 0) {
         if ((parent.getStyle () & DWT.NO_RADIO_GROUP) is 0) {
             selectRadio ();
--- a/dwt/widgets/ToolTip.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/ToolTip.d	Sat May 17 17:34:28 2008 +0200
@@ -488,7 +488,7 @@
                     nY = pt.y;
                 }
             }
-            int lParam = (nX & 0xFFFF) | ((nY << 16) & 0xFFFF0000);
+            int /*long*/ lParam = OS.MAKELPARAM (nX, nY);
             OS.SendMessage (hwndToolTip_, OS.TTM_TRACKPOSITION, 0, lParam);
 
             /*
--- a/dwt/widgets/Tracker.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/Tracker.d	Sat May 17 17:34:28 2008 +0200
@@ -55,7 +55,8 @@
     bool tracking, cancelled, stippled;
     Rectangle [] rectangles, proportions;
     Rectangle bounds;
-    HCURSOR resizeCursor, clientCursor;
+    HCURSOR resizeCursor;
+    Cursor clientCursor;
     int cursorOrientation = DWT.NONE;
     bool inEvent = false;
     HWND hwndTransparent;
@@ -507,11 +508,11 @@
             null,
             OS.GetModuleHandle (null),
             null);
-        oldProc = cast(WNDPROC) OS.GetWindowLong (hwndTransparent, OS.GWL_WNDPROC);
+        oldProc = cast(WNDPROC) OS.GetWindowLongPtr (hwndTransparent, OS.GWLP_WNDPROC);
         //newProc = new Callback (this, "transparentProc", 4); //$NON-NLS-1$
         //int newProcAddress = newProc.getAddress ();
         //if (newProcAddress is 0) DWT.error (DWT.ERROR_NO_MORE_CALLBACKS);
-        OS.SetWindowLong (hwndTransparent, OS.GWL_WNDPROC, cast(int) &transparentFunc );
+        OS.SetWindowLongPtr (hwndTransparent, OS.GWLP_WNDPROC, cast(LONG_PTR) &transparentFunc );
 
         //PORTING_FIXME: Vista version
         version( VISTA ) if (isVista) {
@@ -788,10 +789,9 @@
  */
 public void setCursor(Cursor newCursor) {
     checkWidget();
-    clientCursor = null;
+    clientCursor = newCursor;
     if (newCursor !is null) {
-        clientCursor = newCursor.handle;
-        if (inEvent) OS.SetCursor (clientCursor);
+        if (inEvent) OS.SetCursor (clientCursor.handle);
     }
 }
 
@@ -858,7 +858,7 @@
             break;
         case OS.WM_SETCURSOR:
             if (clientCursor !is null) {
-                OS.SetCursor (clientCursor);
+                OS.SetCursor (clientCursor.handle);
                 return 1;
             }
             if (resizeCursor !is null) {
@@ -906,7 +906,7 @@
             }
         default:
     }
-    return OS.CallWindowProc (oldProc, hwnd, msg, wParam, lParam);
+    return oldProc( hwnd, msg, wParam, lParam);
 }
 
 void update () {
@@ -1063,11 +1063,11 @@
     return result;
 }
 
-LRESULT wmMouse (int message, int wParam, int lParam) {
+LRESULT wmMouse (int message, int /*long*/ wParam, int /*long*/ lParam) {
     bool isMirrored = parent !is null && (parent.style & DWT.MIRRORED) !is 0;
     int newPos = OS.GetMessagePos ();
-    int newX = cast(short) (newPos & 0xFFFF);
-    int newY = cast(short) (newPos >> 16);
+    int newX = OS.GET_X_LPARAM (newPos);
+    int newY = OS.GET_Y_LPARAM (newPos);
     if (newX !is oldX || newY !is oldY) {
         Rectangle [] oldRectangles = rectangles;
         bool oldStippled = stippled;
--- a/dwt/widgets/Tree.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/Tree.d	Sat May 17 17:34:28 2008 +0200
@@ -37,6 +37,7 @@
 import dwt.widgets.Control;
 import dwt.widgets.Listener;
 import dwt.widgets.Widget;
+import dwt.widgets.Table;
 
 import dwt.dwthelper.utils;
 
@@ -77,12 +78,13 @@
  * </pre></code>
  * </p><p>
  * Note that although this class is a subclass of <code>Composite</code>,
- * it does not make sense to add <code>Control</code> children to it,
- * or set a layout on it.
+ * it does not normally make sense to add <code>Control</code> children to
+ * it, or set a layout on it, unless implementing something like a cell
+ * editor.
  * </p><p>
  * <dl>
  * <dt><b>Styles:</b></dt>
- * <dd>SINGLE, MULTI, CHECK, FULL_SELECTION, VIRTUAL</dd>
+ * <dd>SINGLE, MULTI, CHECK, FULL_SELECTION, VIRTUAL, NO_SCROLL</dd>
  * <dt><b>Events:</b></dt>
  * <dd>Selection, DefaultSelection, Collapse, Expand, SetData, MeasureItem, EraseItem, PaintItem</dd>
  * </dl>
@@ -102,9 +104,11 @@
 
     TreeItem [] items;
     TreeColumn [] columns;
+    int columnCount;
     ImageList imageList, headerImageList;
     TreeItem currentItem;
     TreeColumn sortColumn;
+    RECT* focusRect;
     HWND hwndParent, hwndHeader;
     HANDLE hAnchor, hInsert, hSelect;
     int lastID;
@@ -177,6 +181,9 @@
  * @see DWT#SINGLE
  * @see DWT#MULTI
  * @see DWT#CHECK
+ * @see DWT#FULL_SELECTION
+ * @see DWT#VIRTUAL
+ * @see DWT#NO_SCROLL
  * @see Widget#checkSubclass
  * @see Widget#getStyle
  */
@@ -187,15 +194,23 @@
 
 static int checkStyle (int style) {
     /*
-    * Feature in Windows.  It is not possible to create
-    * a tree that scrolls and does not have scroll bars.
-    * The TVS_NOSCROLL style will remove the scroll bars
-    * but the tree will never scroll.  Therefore, no matter
-    * what style bits are specified, set the H_SCROLL and
-    * V_SCROLL bits so that the DWT style will match the
-    * widget that Windows creates.
+    * Feature in Windows.  Even when WS_HSCROLL or
+    * WS_VSCROLL is not specified, Windows creates
+    * trees and tables with scroll bars.  The fix
+    * is to set H_SCROLL and V_SCROLL.
+    *
+    * NOTE: This code appears on all platforms so that
+    * applications have consistent scroll bar behavior.
     */
-    style |= DWT.H_SCROLL | DWT.V_SCROLL;
+    if ((style & DWT.NO_SCROLL) is 0) {
+        style |= DWT.H_SCROLL | DWT.V_SCROLL;
+    }
+    /*
+    * Note: Windows only supports TVS_NOSCROLL and TVS_NOHSCROLL.
+    */
+    if ((style & DWT.H_SCROLL) !is 0 && (style & DWT.V_SCROLL) is 0) {
+        style |= DWT.V_SCROLL;
+    }
     return checkBits (style, DWT.SINGLE, DWT.MULTI, 0, 0, 0, 0);
 }
 
@@ -215,10 +230,17 @@
         case DWT.PaintItem: {
             customDraw = true;
             style |= DWT.DOUBLE_BUFFERED;
+            if (isCustomToolTip ()) createItemToolTips ();
             OS.SendMessage (handle, OS.TVM_SETSCROLLTIME, 0, 0);
             int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
-            bits |= OS.TVS_NOTOOLTIPS;
-            if (eventType is DWT.MeasureItem) bits |= OS.TVS_NOHSCROLL;
+            if (eventType is DWT.MeasureItem) {
+                if (explorerTheme) {
+                    int bits1 = OS.SendMessage (handle, OS.TVM_GETEXTENDEDSTYLE, 0, 0);
+                    bits1 &= ~OS.TVS_EX_AUTOHSCROLL;
+                    OS.SendMessage (handle, OS.TVM_SETEXTENDEDSTYLE, 0, bits1);
+                }
+                bits |= OS.TVS_NOHSCROLL;
+            }
             /*
             * Feature in Windows.  When the tree has the style
             * TVS_FULLROWSELECT, the background color for the
@@ -419,16 +441,14 @@
             }
         }
     }
-    int count = 0;
     int [] order = null;
     RECT clientRect;
     OS.GetClientRect (scrolledHandle (), &clientRect);
     if (hwndHeader !is null) {
         OS.MapWindowPoints (hwndParent, handle, cast(POINT*) &clientRect, 2);
-        count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-        if (count !is 0) {
-            order = new int [count];
-            OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, cast(int) order.ptr);
+        if (columnCount !is 0) {
+            order = new int [columnCount];
+            OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, columnCount, cast(int) order.ptr);
         }
     }
     int sortIndex = -1, clrSortBk = -1;
@@ -442,9 +462,9 @@
     }
     int x = 0;
     Point size = null;
-    for (int i=0; i<Math.max (1, count); i++) {
+    for (int i=0; i<Math.max (1, columnCount); i++) {
         int index = order is null ? i : order [i], width = nmcd.nmcd.rc.right - nmcd.nmcd.rc.left;
-        if (count > 0 && hwndHeader !is null) {
+        if (columnCount > 0 && hwndHeader !is null) {
             HDITEM hdItem;
             hdItem.mask = OS.HDI_WIDTH;
             OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem);
@@ -464,7 +484,7 @@
                             itemRect.right += EXPLORER_EXTRA + 1;
                             pClipRect.left = itemRect.left;
                             pClipRect.right = itemRect.right;
-                            if (count > 0 && hwndHeader !is null) {
+                            if (columnCount > 0 && hwndHeader !is null) {
                                 HDITEM hdItem;
                                 hdItem.mask = OS.HDI_WIDTH;
                                 OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem);
@@ -473,11 +493,11 @@
                         }
                         RECT pRect;
                         OS.SetRect (&pRect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom);
-                        if (count > 0 && hwndHeader !is null) {
+                        if (columnCount > 0 && hwndHeader !is null) {
                             int totalWidth = 0;
                             HDITEM hdItem;
                             hdItem.mask = OS.HDI_WIDTH;
-                            for (int j=0; j<count; j++) {
+                            for (int j=0; j<columnCount; j++) {
                                 OS.SendMessage (hwndHeader, OS.HDM_GETITEM, j, &hdItem);
                                 totalWidth += hdItem.cxy;
                             }
@@ -498,22 +518,6 @@
                     }
                     if (draw) fillBackground (hDC, OS.GetBkColor (hDC), &pClipRect);
                 }
-            } else {
-                if (explorerTheme && hooks (DWT.EraseItem)) {
-                    if ((selected && !ignoreDrawSelection) || (hot && !ignoreDrawHot)) {
-                        RECT pRect = item.getBounds (index, true, true, false, false, false, hDC);
-                        RECT pClipRect = item.getBounds (index, true, true, false, false, true, hDC);
-                        pRect.left -= EXPLORER_EXTRA;
-                        pRect.right += EXPLORER_EXTRA;
-                        pClipRect.left -= EXPLORER_EXTRA;
-                        pClipRect.right += EXPLORER_EXTRA;
-                        auto hTheme = OS.OpenThemeData (handle, cast(TCHAR*) Display.TREEVIEW);
-                        int iStateId = selected ? OS.TREIS_SELECTED : OS.TREIS_HOT;
-                        if (OS.GetFocus () !is handle && selected && !hot) iStateId = OS.TREIS_SELECTEDNOTFOCUS;
-                        OS.DrawThemeBackground (hTheme, hDC, OS.TVP_TREEITEM, iStateId, &pRect, &pClipRect);
-                        OS.CloseThemeData (hTheme);
-                    }
-                }
             }
         }
         if (x + width > clientRect.left) {
@@ -579,8 +583,7 @@
                 backgroundRect = &rect;
             }
             int clrText = -1, clrTextBk = -1;
-            HFONT hFont = item.cellFont !is null ? item.cellFont [index] : cast(HFONT)-1;
-            if (hFont is cast(HFONT)-1) hFont = item.font;
+            auto hFont = item.fontHandle (index);
             if (selectionForeground !is -1) clrText = selectionForeground;
             if (OS.IsWindowEnabled (handle)) {
                 bool drawForeground = false;
@@ -623,26 +626,8 @@
             if (drawItem) {
                 if (i !is 0) {
                     if (hooks (DWT.MeasureItem)) {
-                        RECT itemRect = item.getBounds (index, true, true, false, false, false, hDC);
-                        int nSavedDC = OS.SaveDC (hDC);
-                        GCData data = new GCData ();
-                        data.device = display;
-                        data.hFont = hFont;
-                        GC gc = GC.win32_new (hDC, data);
-                        Event event = new Event ();
-                        event.item = item;
-                        event.index = index;
-                        event.gc = gc;
-                        event.x = itemRect.left;
-                        event.y = itemRect.top;
-                        event.width = itemRect.right - itemRect.left;
-                        event.height = itemRect.bottom - itemRect.top;
-                        sendEvent (DWT.MeasureItem, event);
-                        event.gc = null;
-                        gc.dispose ();
-                        OS.RestoreDC (hDC, nSavedDC);
+                        sendMeasureItemEvent (item, index, hDC);
                         if (isDisposed () || item.isDisposed ()) break;
-                        if (event.height > getItemHeight ()) setItemHeight (event.height);
                     }
                     if (hooks (DWT.EraseItem)) {
                         RECT cellRect = item.getBounds (index, true, true, true, true, true, hDC);
@@ -655,7 +640,7 @@
                             if (clrText !is -1) data.foreground = clrText;
                             if (clrTextBk !is -1) data.background = clrTextBk;
                         }
-                        data.hFont = hFont;
+                        data.font = item.getFont (index);
                         data.uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
                         GC gc = GC.win32_new (hDC, data);
                         Event event = new Event ();
@@ -709,12 +694,12 @@
                                     if (!explorerTheme) {
                                         drawBackground = true;
                                         ignoreDrawBackground = false;
-                                        if (handle is OS.GetFocus () && OS.IsWindowEnabled (handle)) {
+                                        if ((handle is OS.GetFocus () || display.getHighContrast ()) && OS.IsWindowEnabled (handle)) {
                                             clrTextBk = OS.GetSysColor (OS.COLOR_HIGHLIGHT);
                                         } else {
                                             clrTextBk = OS.GetSysColor (OS.COLOR_3DFACE);
                                         }
-                                        if (!ignoreFullSelection && index is count - 1) {
+                                        if (!ignoreFullSelection && index is columnCount - 1) {
                                             RECT* selectionRect = new RECT ();
                                             OS.SetRect (selectionRect, backgroundRect.left, backgroundRect.top, nmcd.nmcd.rc.right, backgroundRect.bottom);
                                             backgroundRect = selectionRect;
@@ -722,11 +707,11 @@
                                     } else {
                                         RECT pRect;
                                         OS.SetRect (&pRect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom);
-                                        if (count > 0 && hwndHeader !is null) {
+                                        if (columnCount > 0 && hwndHeader !is null) {
                                             int totalWidth = 0;
                                             HDITEM hdItem;
                                             hdItem.mask = OS.HDI_WIDTH;
-                                            for (int j=0; j<count; j++) {
+                                            for (int j=0; j<columnCount; j++) {
                                                 OS.SendMessage (hwndHeader, OS.HDM_GETITEM, j, &hdItem);
                                                 totalWidth += hdItem.cxy;
                                             }
@@ -737,7 +722,7 @@
                                                 pRect.left = clientRect.left;
                                                 pRect.right = clientRect.right;
                                             }
-                                            if (index is count - 1) {
+                                            if (index is columnCount - 1) {
                                                 RECT* selectionRect = new RECT ();
                                                 OS.SetRect (selectionRect, backgroundRect.left, backgroundRect.top, pRect.right, backgroundRect.bottom);
                                                 backgroundRect = selectionRect;
@@ -796,17 +781,16 @@
                     if (image !is null) {
                         Rectangle bounds = image.getBounds ();
                         if (size is null) size = getImageSize ();
-                        //int y = rect.top + (index is 0 ? (getItemHeight () - size.y) / 2 : 0);
-                        int y = rect.top;
                         if (!ignoreDrawForeground) {
-                            //TODO - share GC, clip the drawing for index is 0
+                            //int y1 = rect.top + (index is 0 ? (getItemHeight () - size.y) / 2 : 0);
+                            int y1 = rect.top;
+                            int x1 = Math.max (rect.left, rect.left - inset + 1);
                             GCData data = new GCData();
                             data.device = display;
                             GC gc = GC.win32_new (hDC, data);
-                            //if (index is 0) { //must clear
-                                //gc.setClipping (rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
-                            //}
-                            gc.drawImage (image, 0, 0, bounds.width, bounds.height, rect.left - inset + 1, y, size.x, size.y);
+                            gc.setClipping (x1, rect.top, rect.right - x1, rect.bottom - rect.top);
+                            gc.drawImage (image, 0, 0, bounds.width, bounds.height, x1, y1, size.x, size.y);
+                            OS.SelectClipRgn (hDC, null);
                             gc.dispose ();
                         }
                         OS.SetRect (&rect, rect.left + size.x + offset, rect.top, rect.right - inset, rect.bottom);
@@ -837,7 +821,7 @@
                             if (strings !is null) string = strings [index];
                         }
                         if (string !is null) {
-                            if (hFont !is cast(HFONT)-1) hFont = OS.SelectObject (hDC, hFont);
+                            if (hFont !is cast(HFONT)-1) hFont = cast(HFONT)OS.SelectObject (hDC, hFont);
                             if (clrText !is -1) clrText = OS.SetTextColor (hDC, clrText);
                             if (clrTextBk !is -1) clrTextBk = OS.SetBkColor (hDC, clrTextBk);
                             int flags = OS.DT_NOPREFIX | OS.DT_SINGLELINE | OS.DT_VCENTER;
@@ -850,7 +834,7 @@
                             TCHAR[] buffer = StrToTCHARs (getCodePage (), string, false);
                             if (!ignoreDrawForeground) OS.DrawText (hDC, buffer.ptr, buffer.length, &rect, flags);
                             OS.DrawText (hDC, buffer.ptr, buffer.length, &rect, flags | OS.DT_CALCRECT);
-                            if (hFont !is cast(HFONT)-1) hFont = OS.SelectObject (hDC, hFont);
+                            if (hFont !is cast(HFONT)-1) hFont = cast(HFONT)OS.SelectObject (hDC, hFont);
                             if (clrText !is -1) clrText = OS.SetTextColor (hDC, clrText);
                             if (clrTextBk !is -1) clrTextBk = OS.SetBkColor (hDC, clrTextBk);
                         }
@@ -863,7 +847,7 @@
                 int nSavedDC = OS.SaveDC (hDC);
                 GCData data = new GCData ();
                 data.device = display;
-                data.hFont = hFont;
+                data.font = item.getFont (index);
                 data.foreground = OS.GetTextColor (hDC);
                 data.background = OS.GetBkColor (hDC);
                 if (selected && (style & DWT.FULL_SELECTION) !is 0) {
@@ -904,6 +888,7 @@
                 int cellHeight = cellRect.bottom - cellRect.top;
                 gc.setClipping (cellRect.left, cellRect.top, cellWidth, cellHeight);
                 sendEvent (DWT.PaintItem, event);
+                if (data.focusDrawn) focusRect = null;
                 event.gc = null;
                 gc.dispose ();
                 OS.RestoreDC (hDC, nSavedDC);
@@ -915,52 +900,42 @@
     }
     if (linesVisible) {
         if ((style & DWT.FULL_SELECTION) !is 0) {
-            if (hwndHeader !is null) {
-                if (OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0) !is 0) {
-                    HDITEM hdItem;
-                    hdItem.mask = OS.HDI_WIDTH;
-                    OS.SendMessage (hwndHeader, OS.HDM_GETITEM, 0, &hdItem);
-                    RECT rect;
-                    OS.SetRect (&rect, nmcd.nmcd.rc.left + hdItem.cxy, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom);
-                    OS.DrawEdge (hDC, &rect, OS.BDR_SUNKENINNER, OS.BF_BOTTOM);
-                }
+            if (columnCount !is 0) {
+                HDITEM hdItem;
+                hdItem.mask = OS.HDI_WIDTH;
+                OS.SendMessage (hwndHeader, OS.HDM_GETITEM, 0, &hdItem);
+                RECT rect;
+                OS.SetRect (&rect, nmcd.nmcd.rc.left + hdItem.cxy, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom);
+                OS.DrawEdge (hDC, &rect, OS.BDR_SUNKENINNER, OS.BF_BOTTOM);
             }
         }
         RECT rect;
         OS.SetRect (&rect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom);
         OS.DrawEdge (hDC, &rect, OS.BDR_SUNKENINNER, OS.BF_BOTTOM);
     }
-    if (!explorerTheme) {
-        if (handle is OS.GetFocus ()) {
-            int uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
-            if ((uiState & OS.UISF_HIDEFOCUS) is 0) {
-                auto hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
-                if (hItem is item.handle) {
-                    if (!ignoreDrawFocus && findImageControl () !is null) {
-                        if ((style & DWT.FULL_SELECTION) !is 0) {
-                            RECT focusRect;
-                            OS.SetRect (&focusRect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom);
-                            if (count > 0 && hwndHeader !is null) {
-                                int width = 0;
-                                HDITEM hdItem;
-                                hdItem.mask = OS.HDI_WIDTH;
-                                for (int j=0; j<count; j++) {
-                                    OS.SendMessage (hwndHeader, OS.HDM_GETITEM, j, &hdItem);
-                                    width += hdItem.cxy;
-                                }
-                                focusRect.left = 0;
-                                RECT rect;
-                                OS.GetClientRect (handle, &rect);
-                                focusRect.right = Math.max (width, rect.right - OS.GetSystemMetrics (OS.SM_CXVSCROLL));
+    if (!ignoreDrawFocus && focusRect !is null) {
+        OS.DrawFocusRect (hDC, focusRect);
+        focusRect = null;
+    } else {
+        if (!explorerTheme) {
+            if (handle is OS.GetFocus ()) {
+                int uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
+                if ((uiState & OS.UISF_HIDEFOCUS) is 0) {
+                    auto hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+                    if (hItem is item.handle) {
+                        if (!ignoreDrawFocus && findImageControl () !is null) {
+                            if ((style & DWT.FULL_SELECTION) !is 0) {
+                                RECT focusRect;
+                                OS.SetRect (&focusRect, 0, nmcd.nmcd.rc.top, clientRect.right + 1, nmcd.nmcd.rc.bottom);
+                                OS.DrawFocusRect (hDC, &focusRect);
+                            } else {
+                                int index = OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, 0, 0);
+                                RECT focusRect = item.getBounds (index, true, false, false, false, false, hDC);
+                                RECT clipRect = item.getBounds (index, true, false, false, false, true, hDC);
+                                OS.IntersectClipRect (hDC, clipRect.left, clipRect.top, clipRect.right, clipRect.bottom);
+                                OS.DrawFocusRect (hDC, &focusRect);
+                                OS.SelectClipRgn (hDC, null);
                             }
-                            OS.DrawFocusRect (hDC, &focusRect);
-                        } else {
-                            int index = OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, 0, 0);
-                            RECT focusRect = item.getBounds (index, true, false, false, false, false, hDC);
-                            RECT clipRect = item.getBounds (index, true, false, false, false, true, hDC);
-                            OS.IntersectClipRect (hDC, clipRect.left, clipRect.top, clipRect.right, clipRect.bottom);
-                            OS.DrawFocusRect (hDC, &focusRect);
-                            OS.SelectClipRgn (hDC, null);
                         }
                     }
                 }
@@ -990,28 +965,23 @@
     if (item is null) return null;
     auto hDC = nmcd.nmcd.hdc;
     int index = hwndHeader !is null ? OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, 0, 0) : 0;
-    HFONT hFont = item.cellFont !is null ? item.cellFont [index] : cast(HFONT)-1;
-    if (hFont is cast(HFONT)-1) hFont = item.font;
+    auto hFont = item.fontHandle (index);
     if (hFont !is cast(HFONT)-1) OS.SelectObject (hDC, hFont);
     if (ignoreCustomDraw || nmcd.nmcd.rc.left is nmcd.nmcd.rc.right) {
         return new LRESULT (hFont is cast(HFONT)-1 ? OS.CDRF_DODEFAULT : OS.CDRF_NEWFONT);
     }
-    int count = 0;
     RECT* clipRect = null;
-    if (hwndHeader !is null) {
-        count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-        if (count !is 0) {
-            bool clip = !printClient;
-            if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
-                clip = true;
-            }
-            if (clip) {
-                clipRect = new RECT ();
-                HDITEM hdItem;
-                hdItem.mask = OS.HDI_WIDTH;
-                OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem);
-                OS.SetRect (clipRect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.left + hdItem.cxy, nmcd.nmcd.rc.bottom);
-            }
+    if (columnCount !is 0) {
+        bool clip = !printClient;
+        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+            clip = true;
+        }
+        if (clip) {
+            clipRect = new RECT ();
+            HDITEM hdItem;
+            hdItem.mask = OS.HDI_WIDTH;
+            OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem);
+            OS.SetRect (clipRect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.left + hdItem.cxy, nmcd.nmcd.rc.bottom);
         }
     }
     int clrText = -1, clrTextBk = -1;
@@ -1034,6 +1004,7 @@
     }
     bool selected = isItemSelected (nmcd);
     bool hot = explorerTheme && (nmcd.nmcd.uItemState & OS.CDIS_HOT) !is 0;
+    bool focused = explorerTheme && (nmcd.nmcd.uItemState & OS.CDIS_FOCUS) !is 0;
     if (OS.IsWindowVisible (handle) && nmcd.nmcd.rc.left < nmcd.nmcd.rc.right && nmcd.nmcd.rc.top < nmcd.nmcd.rc.bottom) {
         if (hFont !is cast(HFONT)-1) OS.SelectObject (hDC, hFont);
         if (linesVisible) {
@@ -1042,49 +1013,25 @@
             OS.DrawEdge (hDC, &rect, OS.BDR_SUNKENINNER, OS.BF_BOTTOM);
         }
         //TODO - BUG - measure and erase sent when first column is clipped
+        Event measureEvent = null;
         if (hooks (DWT.MeasureItem)) {
-            RECT itemRect = item.getBounds (index, true, true, false, false, false, hDC);
-            int nSavedDC = OS.SaveDC (hDC);
-            GCData data = new GCData ();
-            data.device = display;
-            data.hFont = hFont;
-            GC gc = GC.win32_new (hDC, data);
-            Event event = new Event ();
-            event.item = item;
-            event.gc = gc;
-            event.index = index;
-            event.x = itemRect.left;
-            event.y = itemRect.top;
-            event.width = itemRect.right - itemRect.left;
-            event.height = itemRect.bottom - itemRect.top;
-            sendEvent (DWT.MeasureItem, event);
-            event.gc = null;
-            gc.dispose ();
-            OS.RestoreDC (hDC, nSavedDC);
+            measureEvent = sendMeasureItemEvent (item, index, hDC);
             if (isDisposed () || item.isDisposed ()) return null;
-            if (hwndHeader !is null) {
-                if (count is 0) {
-                    if (event.x + event.width > scrollWidth) {
-                        setScrollWidth (scrollWidth = event.x + event.width);
-                    }
-                }
-            }
-            if (event.height > getItemHeight ()) setItemHeight (event.height);
         }
         selectionForeground = -1;
         ignoreDrawForeground = ignoreDrawBackground = ignoreDrawSelection = ignoreDrawFocus = ignoreDrawHot = ignoreFullSelection = false;
         if (hooks (DWT.EraseItem)) {
             RECT rect;
             OS.SetRect (&rect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom);
-            if (OS.IsWindowEnabled (handle) || findImageControl () !is null) {
-                drawBackground (hDC, &rect);
-            } else {
-                fillBackground (hDC, OS.GetBkColor (hDC), &rect);
-            }
             RECT cellRect = item.getBounds (index, true, true, true, true, true, hDC);
             if (clrSortBk !is -1) {
-                RECT fullRect = item.getBounds (index, true, true, true, true, true, hDC);
-                drawBackground (hDC, &fullRect, clrSortBk);
+                drawBackground (hDC, &cellRect, clrSortBk);
+            } else {
+                if (OS.IsWindowEnabled (handle) || findImageControl () !is null) {
+                    drawBackground (hDC, &rect);
+                } else {
+                    fillBackground (hDC, OS.GetBkColor (hDC), &rect);
+                }
             }
             int nSavedDC = OS.SaveDC (hDC);
             GCData data = new GCData ();
@@ -1100,7 +1047,7 @@
                 if (clrTextBk !is -1) data.background = clrTextBk;
             }
             data.uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
-            if (hFont !is cast(HFONT)-1) data.hFont = hFont;
+            data.font = item.getFont (index);
             GC gc = GC.win32_new (hDC, data);
             Event event = new Event ();
             event.index = index;
@@ -1115,7 +1062,10 @@
                 if (OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0) is nmcd.nmcd.dwItemSpec) {
                     if (handle is OS.GetFocus ()) {
                         int uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
-                        if ((uiState & OS.UISF_HIDEFOCUS) is 0) event.detail |= DWT.FOCUSED;
+                        if ((uiState & OS.UISF_HIDEFOCUS) is 0) {
+                            focused = true;
+                            event.detail |= DWT.FOCUSED;
+                        }
                     }
                 }
             }
@@ -1144,11 +1094,14 @@
                 bool draw = !selected && !hot;
                 if (!explorerTheme && selected) draw = !ignoreDrawSelection;
                 if (draw) {
-                    if (count is 0) {
+                    if (columnCount is 0) {
                         if ((style & DWT.FULL_SELECTION) !is 0) {
                             fillBackground (hDC, clrTextBk, &rect);
                         } else {
-                            RECT textRect = item.getBounds (index, true, false, true, false, true, hDC);
+                            RECT textRect = item.getBounds (index, true, false, false, false, true, hDC);
+                            if (measureEvent !is null) {
+                                textRect.right = Math.min (cellRect.right, measureEvent.x + measureEvent.width);
+                            }
                             fillBackground (hDC, clrTextBk, &textRect);
                         }
                     } else {
@@ -1161,7 +1114,25 @@
                 if (!selected && !hot) {
                     selectionForeground = clrText = OS.GetSysColor (OS.COLOR_HIGHLIGHTTEXT);
                 }
-                if (!explorerTheme) {
+                if (explorerTheme) {
+                    if ((style & DWT.FULL_SELECTION) is 0) {
+                        RECT pRect = item.getBounds (index, true, true, false, false, false, hDC);
+                        RECT pClipRect = item.getBounds (index, true, true, true, false, true, hDC);
+                        if (measureEvent !is null) {
+                            pRect.right = Math.min (pClipRect.right, measureEvent.x + measureEvent.width);
+                        } else {
+                            pRect.right += EXPLORER_EXTRA;
+                            pClipRect.right += EXPLORER_EXTRA;
+                        }
+                        pRect.left -= EXPLORER_EXTRA;
+                        pClipRect.left -= EXPLORER_EXTRA;
+                        auto hTheme = OS.OpenThemeData (handle, Display.TREEVIEW.ptr);
+                        int iStateId = selected ? OS.TREIS_SELECTED : OS.TREIS_HOT;
+                        if (OS.GetFocus () !is handle && selected && !hot) iStateId = OS.TREIS_SELECTEDNOTFOCUS;
+                        OS.DrawThemeBackground (hTheme, hDC, OS.TVP_TREEITEM, iStateId, &pRect, &pClipRect);
+                        OS.CloseThemeData (hTheme);
+                    }
+                } else {
                     /*
                     * Feature in Windows.  When the tree has the style
                     * TVS_FULLROWSELECT, the background color for the
@@ -1170,13 +1141,16 @@
                     * is to emulate TVS_FULLROWSELECT.
                     */
                     if ((style & DWT.FULL_SELECTION) !is 0) {
-                        if ((style & DWT.FULL_SELECTION) !is 0 && count is 0) {
+                        if ((style & DWT.FULL_SELECTION) !is 0 && columnCount is 0) {
                             fillBackground (hDC, OS.GetBkColor (hDC), &rect);
                         } else {
                             fillBackground (hDC, OS.GetBkColor (hDC), &cellRect);
                         }
                     } else {
                         RECT textRect = item.getBounds (index, true, false, false, false, true, hDC);
+                        if (measureEvent !is null) {
+                            textRect.right = Math.min (cellRect.right, measureEvent.x + measureEvent.width);
+                        }
                         fillBackground (hDC, OS.GetBkColor (hDC), &textRect);
                     }
                 }
@@ -1203,6 +1177,16 @@
                     OS.MoveMemory (lParam, nmcd, NMTVCUSTOMDRAW.sizeof);
                 }
             }
+            if (focused && !ignoreDrawFocus && (style & DWT.FULL_SELECTION) is 0) {
+                RECT textRect = item.getBounds (index, true, explorerTheme, false, false, true, hDC);
+                if (measureEvent !is null) {
+                    textRect.right = Math.min (cellRect.right, measureEvent.x + measureEvent.width);
+                }
+                nmcd.nmcd.uItemState &= ~OS.CDIS_FOCUS;
+                OS.MoveMemory (lParam, nmcd, NMTVCUSTOMDRAW.sizeof);
+                if( focusRect is null ) focusRect = new RECT;
+                *focusRect = textRect;
+            }
             if (explorerTheme) {
                 if (selected || (hot && ignoreDrawHot)) nmcd.nmcd.uItemState &= ~OS.CDIS_HOT;
                 OS.MoveMemory (cast(void*)lParam, nmcd, NMTVCUSTOMDRAW.sizeof);
@@ -1260,7 +1244,7 @@
             if (clrTextBk !is -1) {
                 int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
                 if ((bits & OS.TVS_FULLROWSELECT) is 0) {
-                    if (count !is 0 && hwndHeader !is null) {
+                    if (columnCount !is 0 && hwndHeader !is null) {
                         RECT rect;
                         HDITEM hdItem;
                         hdItem.mask = OS.HDI_WIDTH;
@@ -1268,8 +1252,7 @@
                         OS.SetRect (&rect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.left + hdItem.cxy, nmcd.nmcd.rc.bottom);
                         if (OS.COMCTL32_MAJOR < 6 || !OS.IsAppThemed ()) {
                             RECT itemRect;
-                            itemRect.left = cast(int) item.handle;
-                            if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 1, &itemRect) !is 0) {
+                            if (OS.TreeView_GetItemRect (handle, item.handle, &itemRect, true)) {
                                 rect.left = Math.min (itemRect.left, rect.right);
                             }
                         }
@@ -1329,7 +1312,7 @@
                     if (clrTextBk !is -1) {
                         if ((style & DWT.FULL_SELECTION) !is 0) {
                             RECT rect;
-                            if (count !is 0) {
+                            if (columnCount !is 0) {
                                 HDITEM hdItem;
                                 hdItem.mask = OS.HDI_WIDTH;
                                 OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem);
@@ -1406,8 +1389,7 @@
                         }
                         if (hItem !is null) {
                             RECT rect;
-                            rect.left = cast(int) hItem;
-                            if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect) !is 0) {
+                            if (OS.TreeView_GetItemRect (handle, hItem, &rect, false)) {
                                 top = rect.bottom;
                             }
                         }
@@ -1429,8 +1411,7 @@
                 RECT rect;
                 HDITEM hdItem;
                 hdItem.mask = OS.HDI_WIDTH;
-                int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-                for (int i=0; i<count; i++) {
+                for (int i=0; i<columnCount; i++) {
                     int index = OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, i, 0);
                     OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem);
                     OS.SetRect (&rect, x, nmcd.nmcd.rc.top, x + hdItem.cxy, nmcd.nmcd.rc.bottom);
@@ -1463,8 +1444,7 @@
                 hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_LASTVISIBLE, 0);
             }
             if (hItem !is null) {
-                rect.left = cast(int) hItem;
-                if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect) !is 0) {
+                if (OS.TreeView_GetItemRect (handle, hItem, &rect, false)) {
                     height = rect.bottom - rect.top;
                 }
             }
@@ -1591,7 +1571,7 @@
         }
         default:
     }
-    int code = OS.CallWindowProc (TreeProc, hwnd, msg, wParam, lParam);
+    int /*long*/ code = OS.CallWindowProc (TreeProc, hwnd, msg, wParam, lParam);
     switch (msg) {
         /* Keyboard messages */
         case OS.WM_KEYDOWN:
@@ -1665,7 +1645,7 @@
         OS.SendMessage (handle, OS.TVM_SETSCROLLTIME, 0, 0);
     }
     if (EXPLORER_THEME) {
-        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0) && OS.IsAppThemed ()) {
             int exStyle = OS.SendMessage (handle, OS.TVM_GETEXTENDEDSTYLE, 0, 0);
             if ((exStyle & OS.TVS_EX_DOUBLEBUFFER) !is 0) style |= DWT.DOUBLE_BUFFERED;
         }
@@ -1674,8 +1654,11 @@
 
 bool checkData (TreeItem item, bool redraw) {
     if ((style & DWT.VIRTUAL) is 0) return true;
-    TreeItem parentItem = item.getParentItem ();
-    return checkData (item, parentItem is null ? indexOf (item) : parentItem.indexOf (item), redraw);
+    if (!item.cached) {
+        TreeItem parentItem = item.getParentItem ();
+        return checkData (item, parentItem is null ? indexOf (item) : parentItem.indexOf (item), redraw);
+    }
+    return true;
 }
 
 bool checkData (TreeItem item, int index, bool redraw) {
@@ -1713,8 +1696,8 @@
     * callers of this method.
     */
     if (drawCount is 0) return false;
-    int hRoot = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
-    int hParent = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hItem);
+    int /*long*/ hRoot = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
+    int /*long*/ hParent = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hItem);
     while (hParent !is hRoot && hParent !is 0) {
         hParent = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hParent);
     }
@@ -1770,6 +1753,7 @@
         item = tvItem.lParam !is -1 ? items [tvItem.lParam] : null;
     }
     if (item !is null) {
+        if ((style & DWT.VIRTUAL) !is 0 && !item.cached) return;
         item.clear ();
         item.redraw ();
     }
@@ -1798,16 +1782,30 @@
     checkWidget ();
     HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
     if (hItem is null) return;
-    TVITEM tvItem;
-    tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
-    clearAll (hItem, &tvItem, all);
+    if (all) {
+        bool redraw = false;
+        for (int i=0; i<items.length; i++) {
+            TreeItem item = items [i];
+            if (item !is null && item !is currentItem) {
+                item.clear ();
+                redraw = true;
+            }
+        }
+        if (redraw) OS.InvalidateRect (handle, null, true);
+    } else {
+        TVITEM tvItem;
+        tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
+        clearAll (hItem, &tvItem, all);
+    }
 }
 
 void clearAll (HANDLE hItem, TVITEM* tvItem, bool all) {
     while (hItem !is null) {
         clear (hItem, tvItem);
-        auto hFirstItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hItem);
-        if (all) clearAll (hFirstItem, tvItem, all);
+        if (all) {
+            auto hFirstItem = cast(HANDLE)OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hItem);
+            clearAll (hFirstItem, tvItem, all);
+        }
         hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hItem);
     }
 }
@@ -1827,8 +1825,7 @@
     if (hwndHeader !is null) {
         HDITEM hdItem;
         hdItem.mask = OS.HDI_WIDTH;
-        int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-        for (int i=0; i<count; i++) {
+        for (int i=0; i<columnCount; i++) {
             OS.SendMessage (hwndHeader, OS.HDM_GETITEM, i, &hdItem);
             width += hdItem.cxy;
         }
@@ -1848,12 +1845,11 @@
             OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
             ignoreCustomDraw = false;
         }
-        rect.left = cast(int) hItem;
-        if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 1, &rect) !is 0) {
+        if (OS.TreeView_GetItemRect (handle, hItem, &rect, true)) {
             width = Math.max (width, rect.right);
             height += rect.bottom - rect.top;
         }
-        hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hItem);
+        hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, hItem);
     }
     if (width is 0) width = DEFAULT_WIDTH;
     if (height is 0) height = DEFAULT_HEIGHT;
@@ -1877,7 +1873,7 @@
 
     /* Use the Explorer theme */
     if (EXPLORER_THEME) {
-        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0) && OS.IsAppThemed ()) {
             explorerTheme = true;
             OS.SetWindowTheme (handle, cast(TCHAR*) Display.EXPLORER, null);
             int bits = OS.TVS_EX_DOUBLEBUFFER | OS.TVS_EX_FADEINOUTEXPANDOS | OS.TVS_EX_RICHTOOLTIP;
@@ -1931,11 +1927,15 @@
 void createHeaderToolTips () {
     static if (OS.IsWinCE) return;
     if (headerToolTipHandle !is null) return;
+    int bits = 0;
+    if (OS.WIN32_VERSION >= OS.VERSION (4, 10)) {
+        if ((style & DWT.RIGHT_TO_LEFT) !is 0) bits |= OS.WS_EX_LAYOUTRTL;
+    }
     headerToolTipHandle = OS.CreateWindowEx (
-        0,
+        bits,
         OS.TOOLTIPS_CLASS.ptr,
         null,
-        0,
+        OS.TTS_NOPREFIX,
         OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
         handle,
         null,
@@ -1954,7 +1954,6 @@
 
 void createItem (TreeColumn column, int index) {
     if (hwndHeader is null) createParent ();
-    int columnCount = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
     if (!(0 <= index && index <= columnCount)) error (DWT.ERROR_INVALID_RANGE);
     if (columnCount is columns.length) {
         TreeColumn [] newColumns = new TreeColumn [columns.length + 4];
@@ -2009,16 +2008,15 @@
                 item.cellForeground = temp;
             }
             if (item.cellFont !is null) {
-                HFONT [] cellFont = item.cellFont;
-                HFONT [] temp = new HFONT [columnCount + 1];
+                Font [] cellFont = item.cellFont;
+                Font [] temp = new Font [columnCount + 1];
                 System.arraycopy (cellFont, 0, temp, 0, index);
                 System.arraycopy (cellFont, index, temp, index + 1, columnCount- index);
-                temp [index] = cast(HFONT)-1;
                 item.cellFont = temp;
             }
         }
     }
-    System.arraycopy (columns, index, columns, index + 1, columnCount - index);
+    System.arraycopy (columns, index, columns, index + 1, columnCount++ - index);
     columns [index] = column;
 
     /*
@@ -2039,11 +2037,13 @@
     if (pszText !is null) OS.HeapFree (hHeap, 0, pszText);
 
     /* When the first column is created, hide the horizontal scroll bar */
-    if (columnCount is 0) {
+    if (columnCount is 1) {
         scrollWidth = 0;
-        int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
-        bits |= OS.TVS_NOHSCROLL;
-        OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+        if ((style & DWT.H_SCROLL) !is 0) {
+            int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+            bits |= OS.TVS_NOHSCROLL;
+            OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+        }
         /*
         * Bug in Windows.  When TVS_NOHSCROLL is set after items
         * have been inserted into the tree, Windows shows the
@@ -2054,13 +2054,17 @@
         if (count !is 0) {
             static if (!OS.IsWinCE) OS.ShowScrollBar (handle, OS.SB_HORZ, false);
         }
+        createItemToolTips ();
+        if (itemToolTipHandle !is null) {
+            OS.SendMessage (itemToolTipHandle, OS.TTM_SETDELAYTIME, OS.TTDT_AUTOMATIC, -1);
+        }
     }
     setScrollWidth ();
     updateImageList ();
     updateScrollBar ();
 
     /* Redraw to hide the items when the first column is created */
-    if (columnCount is 0 && OS.SendMessage (handle, OS.TVM_GETCOUNT, 0, 0) !is 0) {
+    if (columnCount is 1 && OS.SendMessage (handle, OS.TVM_GETCOUNT, 0, 0) !is 0) {
         OS.InvalidateRect (handle, null, true);
     }
 
@@ -2148,12 +2152,9 @@
         items [id] = item;
     }
     if (hFirstItem is null) {
-        switch ( cast(int) hInsertAfter) {
-            case OS.TVI_FIRST:
-            case OS.TVI_LAST:
-                hFirstIndexOf = hLastIndexOf = hFirstItem = hNewItem;
-                itemCount = lastIndexOf = 0;
-            default:
+        if (cast(int)hInsertAfter is OS.TVI_FIRST || cast(int)hInsertAfter is OS.TVI_LAST) {
+            hFirstIndexOf = hLastIndexOf = hFirstItem = hNewItem;
+            itemCount = lastIndexOf = 0;
         }
     }
     if (hFirstItem is hFirstIndexOf && itemCount !is -1) itemCount++;
@@ -2168,8 +2169,7 @@
         if (fixParent) {
             if (drawCount is 0 && OS.IsWindowVisible (handle)) {
                 RECT rect;
-                rect.left = cast(int) hParent;
-                if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect) !is 0) {
+                if (OS.TreeView_GetItemRect (handle, hParent, &rect, false)) {
                     OS.InvalidateRect (handle, &rect, true);
                 }
             }
@@ -2184,8 +2184,7 @@
         if ((style & DWT.VIRTUAL) !is 0) {
             if (currentItem !is null) {
                 RECT rect;
-                rect.left = cast(int) hNewItem;
-                if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect) !is 0) {
+                if (OS.TreeView_GetItemRect (handle, hNewItem, &rect, false)) {
                     RECT damageRect;
                     bool damaged = cast(bool) OS.GetUpdateRect (handle, &damageRect, true);
                     if (damaged && damageRect.top < rect.bottom) {
@@ -2212,28 +2211,36 @@
 void createItemToolTips () {
     static if (OS.IsWinCE) return;
     if (itemToolTipHandle !is null) return;
-    int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
-    bits |= OS.TVS_NOTOOLTIPS;
-    OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+    int bits1 = OS.GetWindowLong (handle, OS.GWL_STYLE);
+    bits1 |= OS.TVS_NOTOOLTIPS;
+    OS.SetWindowLong (handle, OS.GWL_STYLE, bits1);
+    int bits2 = 0;
+    if (OS.WIN32_VERSION >= OS.VERSION (4, 10)) {
+        if ((style & DWT.RIGHT_TO_LEFT) !is 0) bits2 |= OS.WS_EX_LAYOUTRTL;
+    }
+    /*
+    * Feature in Windows.  For some reason, when the user
+    * clicks on a tool tip, it temporarily takes focus, even
+    * when WS_EX_NOACTIVATE is specified.  The fix is to
+    * use WS_EX_TRANSPARENT, even though WS_EX_TRANSPARENT
+    * is documented to affect painting, not hit testing.
+    *
+    * NOTE: Windows 2000 doesn't have the problem and
+    * setting WS_EX_TRANSPARENT causes pixel corruption.
+    */
+    if (OS.COMCTL32_MAJOR >= 6) bits2 |= OS.WS_EX_TRANSPARENT;
     itemToolTipHandle = OS.CreateWindowEx (
-        0,
+        bits2,
         OS.TOOLTIPS_CLASS.ptr,
         null,
-        0,
+        OS.TTS_NOPREFIX | OS.TTS_NOANIMATE | OS.TTS_NOFADE,
         OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
         handle,
         null,
         OS.GetModuleHandle (null),
         null);
     if (itemToolTipHandle is null) error (DWT.ERROR_NO_HANDLES);
-    /*
-    * Feature in Windows.  Despite the fact that the
-    * tool tip text contains \r\n, the tooltip will
-    * not honour the new line unless TTM_SETMAXTIPWIDTH
-    * is set.  The fix is to set TTM_SETMAXTIPWIDTH to
-    * a large value.
-    */
-    OS.SendMessage (itemToolTipHandle, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF);
+    OS.SendMessage (itemToolTipHandle, OS.TTM_SETDELAYTIME, OS.TTDT_INITIAL, 0);
     TOOLINFO lpti;
     lpti.cbSize = TOOLINFO.sizeof;
     lpti.hwnd = handle;
@@ -2266,7 +2273,7 @@
         OS.GetModuleHandle (null),
         null);
     if (hwndParent is null) error (DWT.ERROR_NO_HANDLES);
-    OS.SetWindowLong (hwndParent, OS.GWL_ID, cast(int) hwndParent);
+    OS.SetWindowLongPtr (hwndParent, OS.GWLP_ID, cast(LONG_PTR)hwndParent);
     int bits = 0;
     if (OS.WIN32_VERSION >= OS.VERSION (4, 10)) {
         bits |= OS.WS_EX_NOINHERITLAYOUT;
@@ -2283,7 +2290,7 @@
         OS.GetModuleHandle (null),
         null);
     if (hwndHeader is null) error (DWT.ERROR_NO_HANDLES);
-    OS.SetWindowLong (hwndHeader, OS.GWL_ID, cast(int) hwndHeader);
+    OS.SetWindowLongPtr (hwndHeader, OS.GWLP_ID, cast(LONG_PTR)hwndHeader);
     if (OS.IsDBLocale) {
         auto hIMC = OS.ImmGetContext (handle);
         OS.ImmAssociateContext (hwndParent, hIMC);
@@ -2323,7 +2330,6 @@
     if (hwndFocus is handle) OS.SetFocus (handle);
     register ();
     subclass ();
-    createItemToolTips ();
 }
 
 override void createWidget () {
@@ -2356,6 +2362,34 @@
 }
 
 /**
+ * Deselects an item in the receiver.  If the item was already
+ * deselected, it remains deselected.
+ *
+ * @param item the item to be deselected
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the item is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the item has been disposed</li>
+ * </ul>
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @since 3.4
+ */
+public void deselect (TreeItem item) {
+    checkWidget ();
+    if (item is null) error (DWT.ERROR_NULL_ARGUMENT);
+    if (item.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT);
+    TVITEM tvItem;
+    tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+    tvItem.stateMask = OS.TVIS_SELECTED;
+    tvItem.hItem = item.handle;
+    OS.SendMessage (handle, OS.TVM_SETITEM, 0, cast(int)&tvItem);
+}
+
+/**
  * Deselects all selected items in the receiver.
  *
  * @exception DWTException <ul>
@@ -2375,8 +2409,8 @@
             OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
         }
     } else {
-        int oldProc = OS.GetWindowLong (handle, OS.GWL_WNDPROC);
-        OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) TreeProc);
+        auto oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC);
+        OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TreeProc);
         if ((style & DWT.VIRTUAL) !is 0) {
             HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
             deselect (hItem, &tvItem, null);
@@ -2389,13 +2423,12 @@
                 }
             }
         }
-        OS.SetWindowLong (handle, OS.GWL_WNDPROC, oldProc);
+        OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc);
     }
 }
 
 void destroyItem (TreeColumn column) {
     if (hwndHeader is null) error (DWT.ERROR_ITEM_NOT_REMOVED);
-    int columnCount = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
     int index = 0;
     while (index < columnCount) {
         if (columns [index] is column) break;
@@ -2462,8 +2495,8 @@
                     item.cellForeground = temp;
                 }
                 if (item.cellFont !is null) {
-                    HFONT [] cellFont = item.cellFont;
-                    HFONT [] temp = new HFONT [columnCount];
+                    Font [] cellFont = item.cellFont;
+                    Font [] temp = new Font [columnCount];
                     System.arraycopy (cellFont, 0, temp, 0, index);
                     System.arraycopy (cellFont, index + 1, temp, index, columnCount - index);
                     item.cellFont = temp;
@@ -2481,10 +2514,13 @@
         scrollWidth = 0;
         if (!hooks (DWT.MeasureItem)) {
             int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
-            bits &= ~OS.TVS_NOHSCROLL;
+            if ((style & DWT.H_SCROLL) !is 0) bits &= ~OS.TVS_NOHSCROLL;
             OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
             OS.InvalidateRect (handle, null, true);
         }
+        if (itemToolTipHandle !is null) {
+            OS.SendMessage (itemToolTipHandle, OS.TTM_SETDELAYTIME, OS.TTDT_INITIAL, 0);
+        }
     } else {
         if (index is 0) {
             columns [0].style &= ~(DWT.LEFT | DWT.RIGHT | DWT.CENTER);
@@ -2552,8 +2588,7 @@
     if ((style & DWT.DOUBLE_BUFFERED) is 0) {
         if (drawCount is 0 && OS.IsWindowVisible (handle)) {
             RECT rect;
-            rect.left = cast(int) hItem;
-            fixRedraw = OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect) is 0;
+            fixRedraw = !OS.TreeView_GetItemRect (handle, hItem, &rect, false);
         }
     }
     if (fixRedraw) {
@@ -2599,8 +2634,7 @@
         */
         if (OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hParent) is 0) {
             RECT rect;
-            rect.left = cast(int) hParent;
-            if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect) !is 0) {
+            if (OS.TreeView_GetItemRect (handle, hParent, &rect, false)) {
                 OS.InvalidateRect (handle, &rect, true);
             }
         }
@@ -2624,6 +2658,21 @@
     updateScrollBar ();
 }
 
+void destroyScrollBar (int type) {
+    super.destroyScrollBar (type);
+    int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+    if ((style & (DWT.H_SCROLL | DWT.V_SCROLL)) is 0) {
+        bits &= ~(OS.WS_HSCROLL | OS.WS_VSCROLL);
+        bits |= OS.TVS_NOSCROLL;
+    } else {
+        if ((style & DWT.H_SCROLL) is 0) {
+            bits &= ~OS.WS_HSCROLL;
+            bits |= OS.TVS_NOHSCROLL;
+        }
+    }
+    OS.SetWindowLong (handle, OS.GWL_STYLE, bits);
+}
+
 override void enableDrag (bool enabled) {
     int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
     if (enabled && hooks (DWT.DragDetect)) {
@@ -2672,6 +2721,66 @@
     updateFullSelection ();
 }
 
+bool findCell (int x, int y, inout TreeItem item, inout int index, inout RECT cellRect, inout RECT itemRect) {
+    bool found = false;
+    TVHITTESTINFO lpht;
+    lpht.pt.x = x;
+    lpht.pt.y = y;
+    OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht);
+    if (lpht.hItem !is null) {
+        item = _getItem (lpht.hItem);
+        POINT pt;
+        pt.x = x;
+        pt.y = y;
+        auto hDC = OS.GetDC (handle);
+        HFONT oldFont;
+        auto newFont = cast(HFONT)OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+        if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
+        RECT rect;
+        if (hwndParent !is null) {
+            OS.GetClientRect (hwndParent, &rect);
+            OS.MapWindowPoints (hwndParent, handle, cast(POINT*)&rect, 2);
+        } else {
+            OS.GetClientRect (handle, &rect);
+        }
+        int count = Math.max (1, columnCount);
+        int [] order = new int [count];
+        if (hwndHeader !is null) OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, cast(int) order.ptr);
+        index = 0;
+        bool quit = false;
+        while (index < count && !quit) {
+            auto hFont = item.fontHandle (order [index]);
+            if (hFont !is cast(HFONT)-1) hFont = OS.SelectObject (hDC, hFont);
+            cellRect = item.getBounds (order [index], true, false, true, false, true, hDC);
+            if (cellRect.left > rect.right) {
+                quit = true;
+            } else {
+                cellRect.right = Math.min (cellRect.right, rect.right);
+                if (OS.PtInRect ( &cellRect, pt)) {
+                    if (isCustomToolTip ()) {
+                        Event event = sendMeasureItemEvent (item, order [index], hDC);
+                        if (isDisposed () || item.isDisposed ()) break;
+                        //itemRect [0] = new RECT ();
+                        itemRect.left = event.x;
+                        itemRect.right = event.x + event.width;
+                        itemRect.top = event.y;
+                        itemRect.bottom = event.y + event.height;
+                    } else {
+                        itemRect = item.getBounds (order [index], true, false, false, false, false, hDC);
+                    }
+                    if (itemRect.right > cellRect.right) found = true;
+                    quit = true;
+                }
+            }
+            if (hFont !is cast(HFONT)-1) OS.SelectObject (hDC, hFont);
+            if (!found) index++;
+        }
+        if (newFont !is null) OS.SelectObject (hDC, oldFont);
+        OS.ReleaseDC (handle, hDC);
+    }
+    return found;
+}
+
 int findIndex (HANDLE hFirstItem, HANDLE hItem) {
     if (hFirstItem is null) return -1;
     if (hFirstItem is hFirstIndexOf) {
@@ -2903,9 +3012,7 @@
  */
 public TreeColumn getColumn (int index) {
     checkWidget ();
-    if (hwndHeader is null) error (DWT.ERROR_INVALID_RANGE);
-    int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-    if (!(0 <= index && index < count)) error (DWT.ERROR_INVALID_RANGE);
+    if (!(0 <= index && index < columnCount)) error (DWT.ERROR_INVALID_RANGE);
     return columns [index];
 }
 
@@ -2927,8 +3034,7 @@
  */
 public int getColumnCount () {
     checkWidget ();
-    if (hwndHeader is null) return 0;
-    return OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
+    return columnCount;
 }
 
 /**
@@ -2961,10 +3067,9 @@
  */
 public int[] getColumnOrder () {
     checkWidget ();
-    if (hwndHeader is null) return new int [0];
-    int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-    int [] order = new int [count];
-    OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, order.ptr);
+    if (columnCount is 0) return null;
+    int [] order = new int [columnCount];
+    OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, columnCount, order.ptr);
     return order;
 }
 
@@ -2999,10 +3104,8 @@
  */
 public TreeColumn [] getColumns () {
     checkWidget ();
-    if (hwndHeader is null) return new TreeColumn [0];
-    int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-    TreeColumn [] result = new TreeColumn [count];
-    System.arraycopy (columns, 0, result, 0, count);
+    TreeColumn [] result = new TreeColumn [columnCount];
+    System.arraycopy (columns, 0, result, 0, columnCount);
     return result;
 }
 
@@ -3086,9 +3189,18 @@
     lpht.pt.y = point.y;
     OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht);
     if (lpht.hItem !is null) {
-        if ((style & DWT.FULL_SELECTION) !is 0 || (lpht.flags & OS.TVHT_ONITEM) !is 0) {
-            return _getItem (lpht.hItem);
-        }
+        int flags = OS.TVHT_ONITEM;
+        if ((style & DWT.FULL_SELECTION) !is 0) {
+            flags |= OS.TVHT_ONITEMRIGHT | OS.TVHT_ONITEMINDENT;
+        } else {
+            if (hooks (DWT.MeasureItem)) {
+                lpht.flags &= ~(OS.TVHT_ONITEMICON | OS.TVHT_ONITEMLABEL);
+                if (hitTestSelection ( lpht.hItem, lpht.pt.x, lpht.pt.y)) {
+                    lpht.flags |= OS.TVHT_ONITEMICON | OS.TVHT_ONITEMLABEL;
+                }
+            }
+        }
+        if ((lpht.flags & flags) !is 0) return _getItem (lpht.hItem);
     }
     return null;
 }
@@ -3328,8 +3440,8 @@
     }
     int count = 0;
     TreeItem [] guess = new TreeItem [(style & DWT.VIRTUAL) !is 0 ? 8 : 1];
-    int oldProc = OS.GetWindowLong (handle, OS.GWL_WNDPROC);
-    OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) TreeProc);
+    int /*long*/ oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC);
+    OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TreeProc);
     if ((style & DWT.VIRTUAL) !is 0) {
         TVITEM tvItem;
         tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM | OS.TVIF_STATE;
@@ -3360,7 +3472,7 @@
             }
         }
     }
-    OS.SetWindowLong (handle, OS.GWL_WNDPROC, oldProc);
+    OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc);
     if (count is 0) return new TreeItem [0];
     if (count is guess.length) return guess;
     TreeItem [] result = new TreeItem [count];
@@ -3368,7 +3480,7 @@
         System.arraycopy (guess, 0, result, 0, count);
         return result;
     }
-    OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) TreeProc);
+    OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TreeProc);
     TVITEM tvItem;
     tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM | OS.TVIF_STATE;
     HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
@@ -3377,7 +3489,7 @@
     if (count !is getSelection (hItem, &tvItem, result, 0, count, bigSelection, false)) {
         getSelection (hItem, &tvItem, result, 0, count, bigSelection, true);
     }
-    OS.SetWindowLong (handle, OS.GWL_WNDPROC, oldProc);
+    OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc);
     return result;
 }
 
@@ -3409,14 +3521,14 @@
         return (state & OS.TVIS_SELECTED) is 0 ? 0 : 1;
     }
     int count = 0;
-    int oldProc = OS.GetWindowLong (handle, OS.GWL_WNDPROC);
+    int /*long*/ oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC);
     TVITEM tvItem_;
     TVITEM* tvItem = null;
     static if (OS.IsWinCE) {
         tvItem = &tvitem_;
         tvItem.mask = OS.TVIF_STATE;
     }
-    OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) TreeProc);
+    OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TreeProc);
     if ((style & DWT.VIRTUAL) !is 0) {
         HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
         count = getSelection (hItem, tvItem, null, 0, -1, false, true);
@@ -3437,7 +3549,7 @@
             }
         }
     }
-    OS.SetWindowLong (handle, OS.GWL_WNDPROC, oldProc);
+    OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc);
     return count;
 }
 
@@ -3520,6 +3632,30 @@
     return hItem !is null ? _getItem (hItem) : null;
 }
 
+bool hitTestSelection (HANDLE hItem, int x, int y) {
+    if (hItem is null) return false;
+    TreeItem item = _getItem (hItem);
+    if (item is null) return false;
+    if (!hooks (DWT.MeasureItem)) return false;
+    bool result = false;
+
+    //BUG? - moved columns, only hittest first column
+    //BUG? - check drag detect
+    int [] order = new int [1], index = new int [1];
+
+    auto hDC = OS.GetDC (handle);
+    HFONT oldFont, newFont = cast(HFONT)OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+    if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
+    auto hFont = item.fontHandle (order [index [0]]);
+    if (hFont !is cast(HFONT)-1) hFont = OS.SelectObject (hDC, hFont);
+    Event event = sendMeasureItemEvent (item, order [index [0]], hDC);
+    if (event.getBounds ().contains (x, y)) result = true;
+    if (newFont !is null) OS.SelectObject (hDC, oldFont);
+    OS.ReleaseDC (handle, hDC);
+//  if (isDisposed () || item.isDisposed ()) return false;
+    return result;
+}
+
 int imageIndex (Image image, int index) {
     if (image is null) return OS.I_IMAGENONE;
     if (imageList is null) {
@@ -3529,6 +3665,11 @@
     int imageIndex = imageList.indexOf (image);
     if (imageIndex is -1) imageIndex = imageList.add (image);
     if (hwndHeader is null || OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, 0, 0) is index) {
+        /*
+        * Feature in Windows.  When setting the same image list multiple
+        * times, Windows does work making this operation slow.  The fix
+        * is to test for the same image list before setting the new one.
+        */
         auto hImageList = imageList.getHandle ();
         auto hOldImageList = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETIMAGELIST, OS.TVSIL_NORMAL, 0);
         if (hOldImageList !is hImageList) {
@@ -3581,9 +3722,7 @@
     checkWidget ();
     if (column is null) error (DWT.ERROR_NULL_ARGUMENT);
     if (column.isDisposed()) error(DWT.ERROR_INVALID_ARGUMENT);
-    if (hwndHeader is null) return -1;
-    int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-    for (int i=0; i<count; i++) {
+    for (int i=0; i<columnCount; i++) {
         if (columns [i] is column) return i;
     }
     return -1;
@@ -3617,6 +3756,10 @@
     return hItem is null ? -1 : findIndex (hItem, item.handle);
 }
 
+bool isCustomToolTip () {
+    return hooks (DWT.MeasureItem);
+}
+
 bool isItemSelected (NMTVCUSTOMDRAW* nmcd) {
     bool selected = false;
     if (OS.IsWindowEnabled (handle)) {
@@ -3686,9 +3829,9 @@
         HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
         if (hItem !is null) {
             RECT rect;
-            rect.left = cast(int) hItem;
-            OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect);
-            OS.InvalidateRect (handle, &rect, true);
+            if (OS.TreeView_GetItemRect (handle, hItem, &rect, false)) {
+                OS.InvalidateRect (handle, &rect, true);
+            }
         }
     } else {
         HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
@@ -3710,9 +3853,9 @@
                     state = OS.SendMessage (handle, OS.TVM_GETITEMSTATE, hItem, OS.TVIS_SELECTED);
                 }
                 if ((state & OS.TVIS_SELECTED) !is 0) {
-                    rect.left = cast(int) hItem;
-                    OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect);
-                    OS.InvalidateRect (handle, &rect, true);
+                    if (OS.TreeView_GetItemRect (handle, hItem, &rect, false)) {
+                        OS.InvalidateRect (handle, &rect, true);
+                    }
                 }
                 hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, hItem);
                 index++;
@@ -3808,12 +3951,6 @@
     if (itemToolTipHandle !is null) OS.DestroyWindow (itemToolTipHandle);
     if (headerToolTipHandle !is null) OS.DestroyWindow (headerToolTipHandle);
     itemToolTipHandle = headerToolTipHandle = null;
-    if (display.isXMouseActive ()) {
-        Shell shell = getShell ();
-        if (shell.lockToolTipControl is this) {
-            shell.lockToolTipControl = null;
-        }
-    }
 }
 
 /**
@@ -3838,7 +3975,7 @@
     bool redraw = drawCount is 0 && OS.IsWindowVisible (handle);
     if (redraw) OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
     shrink = ignoreShrink = true;
-    int result = OS.SendMessage (handle, OS.TVM_DELETEITEM, 0, OS.TVI_ROOT);
+    int /*long*/ result = OS.SendMessage (handle, OS.TVM_DELETEITEM, 0, OS.TVI_ROOT);
     ignoreShrink = false;
     if (redraw) {
         OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
@@ -3972,8 +4109,26 @@
         hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXT, hItem);
         itemCount++;
     }
+    bool expanded = false;
     TVITEM tvItem;
     tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM;
+    if (!redraw && (style & DWT.VIRTUAL) !is 0) {
+        if (OS.IsWinCE) {
+            tvItem.hItem = hParent;
+            tvItem.mask = OS.TVIF_STATE;
+            OS.SendMessage (handle, OS.TVM_GETITEM, 0, cast(int)&tvItem);
+            expanded = (tvItem.state & OS.TVIS_EXPANDED) !is 0;
+        } else {
+            /*
+            * Bug in Windows.  Despite the fact that TVM_GETITEMSTATE claims
+            * to return only the bits specified by the stateMask, when called
+            * with TVIS_EXPANDED, the entire state is returned.  The fix is
+            * to explicitly check for the TVIS_EXPANDED bit.
+            */
+            int state = OS.SendMessage (handle, OS.TVM_GETITEMSTATE, hParent, OS.TVIS_EXPANDED);
+            expanded = (state & OS.TVIS_EXPANDED) !is 0;
+        }
+    }
     while (hItem !is null) {
         tvItem.hItem = hItem;
         OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem);
@@ -3988,7 +4143,9 @@
     }
     if ((style & DWT.VIRTUAL) !is 0) {
         for (int i=itemCount; i<count; i++) {
+            if (expanded) ignoreShrink = true;
             createItem (null, hParent, cast(HANDLE) OS.TVI_LAST, null);
+            if (expanded) ignoreShrink = false;
         }
     } else {
         shrink = true;
@@ -4053,8 +4210,7 @@
 
 override HWND scrolledHandle () {
     if (hwndHeader is null) return handle;
-    int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-    return count is 0 ? handle : hwndParent;
+    return columnCount is 0 && scrollWidth is 0 ? handle : hwndParent;
 }
 
 void select (HANDLE hItem, TVITEM* tvItem) {
@@ -4068,6 +4224,94 @@
 }
 
 /**
+ * Selects an item in the receiver.  If the item was already
+ * selected, it remains selected.
+ *
+ * @param item the item to be selected
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the item is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the item has been disposed</li>
+ * </ul>
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @since 3.4
+ */
+public void select (TreeItem item) {
+    checkWidget ();
+    if (item is null) error (DWT.ERROR_NULL_ARGUMENT);
+    if (item.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT);
+    if ((style & DWT.SINGLE) !is 0) {
+        auto hItem = item.handle;
+        int state = 0;
+        static if (OS.IsWinCE) {
+            TVITEM tvItem;
+            tvItem.hItem = hItem;
+            tvItem.mask = OS.TVIF_STATE;
+            OS.SendMessage (handle, OS.TVM_GETITEM, 0, cast(int)&tvItem);
+            state = tvItem.state;
+        } else {
+            state = OS.SendMessage (handle, OS.TVM_GETITEMSTATE, cast(int)&hItem, OS.TVIS_SELECTED);
+        }
+        if ((state & OS.TVIS_SELECTED) !is 0) return;
+        /*
+        * Feature in Windows.  When an item is selected with
+        * TVM_SELECTITEM and TVGN_CARET, the tree expands and
+        * scrolls to show the new selected item.  Unfortunately,
+        * there is no other way in Windows to set the focus
+        * and select an item.  The fix is to save the current
+        * scroll bar positions, turn off redraw, select the item,
+        * then scroll back to the original position and redraw
+        * the entire tree.
+        */
+        SCROLLINFO* hInfo = null;
+        int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+        if ((bits & (OS.TVS_NOHSCROLL | OS.TVS_NOSCROLL)) is 0) {
+            hInfo = new SCROLLINFO ();
+            hInfo.cbSize = SCROLLINFO.sizeof;
+            hInfo.fMask = OS.SIF_ALL;
+            OS.GetScrollInfo (handle, OS.SB_HORZ, hInfo);
+        }
+        SCROLLINFO vInfo;
+        vInfo.cbSize = SCROLLINFO.sizeof;
+        vInfo.fMask = OS.SIF_ALL;
+        OS.GetScrollInfo (handle, OS.SB_VERT, &vInfo);
+        bool redraw = drawCount is 0 && OS.IsWindowVisible (handle);
+        if (redraw) {
+            OS.UpdateWindow (handle);
+            OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
+        }
+        setSelection (item);
+        if (hInfo !is null) {
+            int /*long*/ hThumb = OS.MAKELPARAM (OS.SB_THUMBPOSITION, hInfo.nPos);
+            OS.SendMessage (handle, OS.WM_HSCROLL, hThumb, 0);
+        }
+        int /*long*/ vThumb = OS.MAKELPARAM (OS.SB_THUMBPOSITION, vInfo.nPos);
+        OS.SendMessage (handle, OS.WM_VSCROLL, vThumb, 0);
+        if (redraw) {
+            OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+            OS.InvalidateRect (handle, null, true);
+            if ((style & DWT.DOUBLE_BUFFERED) is 0) {
+                int oldStyle = style;
+                style |= DWT.DOUBLE_BUFFERED;
+                OS.UpdateWindow (handle);
+                style = oldStyle;
+            }
+        }
+        return;
+    }
+    TVITEM tvItem;
+    tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+    tvItem.stateMask = OS.TVIS_SELECTED;
+    tvItem.state = OS.TVIS_SELECTED;
+    tvItem.hItem = item.handle;
+    OS.SendMessage (handle, OS.TVM_SETITEM, 0, cast(int)&tvItem);
+}
+
+/**
  * Selects all of the items in the receiver.
  * <p>
  * If the receiver is single-select, do nothing.
@@ -4085,8 +4329,8 @@
     tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
     tvItem.state = OS.TVIS_SELECTED;
     tvItem.stateMask = OS.TVIS_SELECTED;
-    int oldProc = OS.GetWindowLong (handle, OS.GWL_WNDPROC);
-    OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) TreeProc);
+    int /*long*/ oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC);
+    OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TreeProc);
     if ((style & DWT.VIRTUAL) !is 0) {
         HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
         select (hItem, &tvItem);
@@ -4099,7 +4343,95 @@
             }
         }
     }
-    OS.SetWindowLong (handle, OS.GWL_WNDPROC, oldProc);
+    OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc);
+}
+
+Event sendEraseItemEvent (TreeItem item, NMTTCUSTOMDRAW* nmcd, int column, RECT* cellRect) {
+    int nSavedDC = OS.SaveDC (nmcd.nmcd.hdc);
+    RECT* insetRect = toolTipInset (cellRect);
+    OS.SetWindowOrgEx (nmcd.nmcd.hdc, insetRect.left, insetRect.top, null);
+    GCData data = new GCData ();
+    data.device = display;
+    data.foreground = OS.GetTextColor (nmcd.nmcd.hdc);
+    data.background = OS.GetBkColor (nmcd.nmcd.hdc);
+    data.font = item.getFont (column);
+    data.uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
+    GC gc = GC.win32_new (nmcd.nmcd.hdc, data);
+    Event event = new Event ();
+    event.item = item;
+    event.index = column;
+    event.gc = gc;
+    event.detail |= DWT.FOREGROUND;
+    event.x = cellRect.left;
+    event.y = cellRect.top;
+    event.width = cellRect.right - cellRect.left;
+    event.height = cellRect.bottom - cellRect.top;
+    //gc.setClipping (event.x, event.y, event.width, event.height);
+    sendEvent (DWT.EraseItem, event);
+    event.gc = null;
+    //int newTextClr = data.foreground;
+    gc.dispose ();
+    OS.RestoreDC (nmcd.nmcd.hdc, nSavedDC);
+    return event;
+}
+
+Event sendMeasureItemEvent (TreeItem item, int index, HDC hDC) {
+    RECT itemRect = item.getBounds (index, true, true, false, false, false, hDC);
+    int nSavedDC = OS.SaveDC (hDC);
+    GCData data = new GCData ();
+    data.device = display;
+    data.font = item.getFont (index);
+    GC gc = GC.win32_new (hDC, data);
+    Event event = new Event ();
+    event.item = item;
+    event.gc = gc;
+    event.index = index;
+    event.x = itemRect.left;
+    event.y = itemRect.top;
+    event.width = itemRect.right - itemRect.left;
+    event.height = itemRect.bottom - itemRect.top;
+    sendEvent (DWT.MeasureItem, event);
+    event.gc = null;
+    gc.dispose ();
+    OS.RestoreDC (hDC, nSavedDC);
+    if (isDisposed () || item.isDisposed ()) return null;
+    if (hwndHeader !is null) {
+        if (columnCount is 0) {
+            if (event.x + event.width > scrollWidth) {
+                setScrollWidth (scrollWidth = event.x + event.width);
+            }
+        }
+    }
+    if (event.height > getItemHeight ()) setItemHeight (event.height);
+    return event;
+}
+
+Event sendPaintItemEvent (TreeItem item, NMTTCUSTOMDRAW* nmcd, int column, RECT* itemRect) {
+    int nSavedDC = OS.SaveDC (nmcd.nmcd.hdc);
+    RECT* insetRect = toolTipInset (itemRect);
+    OS.SetWindowOrgEx (nmcd.nmcd.hdc, insetRect.left, insetRect.top, null);
+    GCData data = new GCData ();
+    data.device = display;
+    data.font = item.getFont (column);
+    data.foreground = OS.GetTextColor (nmcd.nmcd.hdc);
+    data.background = OS.GetBkColor (nmcd.nmcd.hdc);
+    data.uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
+    GC gc = GC.win32_new (nmcd.nmcd.hdc, data);
+    Event event = new Event ();
+    event.item = item;
+    event.index = column;
+    event.gc = gc;
+    event.detail |= DWT.FOREGROUND;
+    event.x = itemRect.left;
+    event.y = itemRect.top;
+    event.width = itemRect.right - itemRect.left;
+    event.height = itemRect.bottom - itemRect.top;
+    //gc.setClipping (cellRect.left, cellRect.top, cellWidth, cellHeight);
+    sendEvent (DWT.PaintItem, event);
+    event.gc = null;
+    gc.dispose ();
+    OS.RestoreDC (nmcd.nmcd.hdc, nSavedDC);
+    return event;
 }
 
 override void setBackgroundImage (HBITMAP hBitmap) {
@@ -4164,24 +4496,6 @@
     updateFullSelection ();
 }
 
-override void setBounds (int x, int y, int width, int height, int flags) {
-    /*
-    * Ensure that the selection is visible when the tree is resized
-    * from a zero size to a size that can show the selection.
-    */
-    bool fixSelection = false;
-    if ((flags & OS.SWP_NOSIZE) is 0 && (width !is 0 || height !is 0)) {
-        if (OS.SendMessage (handle, OS.TVM_GETVISIBLECOUNT, 0, 0) is 0) {
-            fixSelection = true;
-        }
-    }
-    super.setBounds (x, y, width, height, flags);
-    if (fixSelection) {
-        HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
-        if (hItem !is null) showItem (hItem);
-    }
-}
-
 override void setCursor () {
     /*
     * Bug in Windows.  Under certain circumstances, when WM_SETCURSOR
@@ -4224,39 +4538,35 @@
 public void setColumnOrder (int [] order) {
     checkWidget ();
     if (order is null) error (DWT.ERROR_NULL_ARGUMENT);
-    int count = 0;
-    if (hwndHeader !is null) {
-        count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-    }
-    if (count is 0) {
+    if (columnCount is 0) {
         if (order.length !is 0) error (DWT.ERROR_INVALID_ARGUMENT);
         return;
     }
-    if (order.length !is count) error (DWT.ERROR_INVALID_ARGUMENT);
-    int [] oldOrder = new int [count];
-    OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, oldOrder.ptr);
+    if (order.length !is columnCount) error (DWT.ERROR_INVALID_ARGUMENT);
+    int [] oldOrder = new int [columnCount];
+    OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, columnCount, oldOrder.ptr);
     bool reorder = false;
-    bool [] seen = new bool [count];
+    bool [] seen = new bool [columnCount];
     for (int i=0; i<order.length; i++) {
         int index = order [i];
-        if (index < 0 || index >= count) error (DWT.ERROR_INVALID_RANGE);
+        if (index < 0 || index >= columnCount) error (DWT.ERROR_INVALID_RANGE);
         if (seen [index]) error (DWT.ERROR_INVALID_ARGUMENT);
         seen [index] = true;
         if (index !is oldOrder [i]) reorder = true;
     }
     if (reorder) {
-        RECT [] oldRects = new RECT [count];
-        for (int i=0; i<count; i++) {
+        RECT [] oldRects = new RECT [columnCount];
+        for (int i=0; i<columnCount; i++) {
             //oldRects [i] = new RECT ();
             OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, i, & oldRects [i]);
         }
         OS.SendMessage (hwndHeader, OS.HDM_SETORDERARRAY, order.length, order.ptr);
         OS.InvalidateRect (handle, null, true);
         updateImageList ();
-        TreeColumn [] newColumns = new TreeColumn [count];
-        System.arraycopy (columns, 0, newColumns, 0, count);
+        TreeColumn [] newColumns = new TreeColumn [columnCount];
+        System.arraycopy (columns, 0, newColumns, 0, columnCount);
         RECT newRect;
-        for (int i=0; i<count; i++) {
+        for (int i=0; i<columnCount; i++) {
             TreeColumn column = newColumns [i];
             if (!column.isDisposed ()) {
                 OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, i, &newRect);
@@ -4453,6 +4763,7 @@
                 hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_INSERTITEM, 0, &tvInsert);
             }
             OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+            updateScrollBar ();
         }
     }
     super.setRedraw (redraw);
@@ -4470,8 +4781,7 @@
     if (hwndHeader is null || hwndParent is null) return;
     int width = 0;
     HDITEM hdItem;
-    int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-    for (int i=0; i<count; i++) {
+    for (int i=0; i<columnCount; i++) {
         hdItem.mask = OS.HDI_WIDTH;
         OS.SendMessage (hwndHeader, OS.HDM_GETITEM, i, &hdItem);
         width += hdItem.cxy;
@@ -4488,8 +4798,7 @@
     SCROLLINFO info;
     info.cbSize = SCROLLINFO.sizeof;
     info.fMask = OS.SIF_RANGE | OS.SIF_PAGE;
-    int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-    if (count is 0 && width is 0) {
+    if (columnCount is 0 && width is 0) {
         OS.GetScrollInfo (hwndParent, OS.SB_HORZ, &info);
         info.nPage = info.nMax + 1;
         OS.SetScrollInfo (hwndParent, OS.SB_HORZ, &info, true);
@@ -4497,14 +4806,16 @@
         info.nPage = info.nMax + 1;
         OS.SetScrollInfo (hwndParent, OS.SB_VERT, &info, true);
     } else {
-        OS.GetClientRect (hwndParent, &rect);
-        OS.GetScrollInfo (hwndParent, OS.SB_HORZ, &info);
-        info.nMax = width;
-        info.nPage = rect.right - rect.left + 1;
-        OS.SetScrollInfo (hwndParent, OS.SB_HORZ, &info, true);
-        info.fMask = OS.SIF_POS;
-        OS.GetScrollInfo (hwndParent, OS.SB_HORZ, &info);
-        left = info.nPos;
+        if ((style & DWT.H_SCROLL) !is 0) {
+            OS.GetClientRect (hwndParent, &rect);
+            OS.GetScrollInfo (hwndParent, OS.SB_HORZ, &info);
+            info.nMax = width;
+            info.nPage = rect.right - rect.left + 1;
+            OS.SetScrollInfo (hwndParent, OS.SB_HORZ, &info, true);
+            info.fMask = OS.SIF_POS;
+            OS.GetScrollInfo (hwndParent, OS.SB_HORZ, &info);
+            left = info.nPos;
+        }
     }
     if (horizontalBar !is null) {
         horizontalBar.setIncrement (INCREMENT);
@@ -4520,7 +4831,7 @@
     SetWindowPos (hwndHeader, cast(HWND)OS.HWND_TOP, pos.x - left, pos.y, pos.cx + left, pos.cy, OS.SWP_NOACTIVATE);
     int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
     int b = (bits & OS.WS_EX_CLIENTEDGE) !is 0 ? OS.GetSystemMetrics (OS.SM_CXEDGE) : 0;
-    int w = pos.cx + (count is 0 && width is 0 ? 0 : OS.GetSystemMetrics (OS.SM_CXVSCROLL));
+    int w = pos.cx + (columnCount is 0 && width is 0 ? 0 : OS.GetSystemMetrics (OS.SM_CXVSCROLL));
     int h = rect.bottom - rect.top - pos.cy;
     bool oldIgnore = ignoreResize;
     ignoreResize = true;
@@ -4641,7 +4952,7 @@
         ignoreSelect = false;
         if (OS.SendMessage (handle, OS.TVM_GETVISIBLECOUNT, 0, 0) is 0) {
             OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_FIRSTVISIBLE, hNewItem);
-            int hParent = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hNewItem);
+            int /*long*/ hParent = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hNewItem);
             if (hParent is 0) OS.SendMessage (handle, OS.WM_HSCROLL, OS.SB_TOP, 0);
         }
         if (fixScroll) {
@@ -4672,8 +4983,8 @@
     TVITEM tvItem;
     tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
     tvItem.stateMask = OS.TVIS_SELECTED;
-    int oldProc = OS.GetWindowLong (handle, OS.GWL_WNDPROC);
-    OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) TreeProc);
+    int /*long*/ oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC);
+    OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TreeProc);
     if ((style & DWT.VIRTUAL) !is 0) {
         HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
         setSelection (hItem, &tvItem, items);
@@ -4702,7 +5013,7 @@
             }
         }
     }
-    OS.SetWindowLong (handle, OS.GWL_WNDPROC, oldProc);
+    OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc);
 }
 
 /**
@@ -4834,8 +5145,7 @@
     } else {
         bool scroll = true;
         RECT itemRect;
-        itemRect.left = cast(int) hItem;
-        if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 1, &itemRect) !is 0) {
+        if (OS.TreeView_GetItemRect (handle, hItem, &itemRect, true)) {
             forceResize ();
             RECT rect;
             OS.GetClientRect (handle, &rect);
@@ -4862,8 +5172,7 @@
     }
     if (hwndParent !is null) {
         RECT itemRect;
-        itemRect.left = cast(int) hItem;
-        if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 1, &itemRect) !is 0) {
+        if (OS.TreeView_GetItemRect (handle, hItem, &itemRect, true)) {
             forceResize ();
             RECT rect;
             OS.GetClientRect (hwndParent, &rect);
@@ -4912,28 +5221,25 @@
     if (column.parent !is this) return;
     int index = indexOf (column);
     if (index is -1) return;
-    int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-    if (0 <= index && index < count) {
-        if (hwndParent !is null) {
-            forceResize ();
-            RECT rect;
-            OS.GetClientRect (hwndParent, &rect);
-            OS.MapWindowPoints (hwndParent, handle, cast(POINT*) &rect, 2);
-            RECT headerRect;
-            OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, &headerRect);
-            bool scroll = headerRect.left < rect.left;
-            if (!scroll) {
-                int width = Math.min (rect.right - rect.left, headerRect.right - headerRect.left);
-                scroll = headerRect.left + width > rect.right;
-            }
-            if (scroll) {
-                SCROLLINFO info;
-                info.cbSize = SCROLLINFO.sizeof;
-                info.fMask = OS.SIF_POS;
-                info.nPos = Math.max (0, headerRect.left - Tree.INSET / 2);
-                OS.SetScrollInfo (hwndParent, OS.SB_HORZ, &info, true);
-                setScrollWidth ();
-            }
+    if (0 <= index && index < columnCount) {
+        forceResize ();
+        RECT rect;
+        OS.GetClientRect (hwndParent, &rect);
+        OS.MapWindowPoints (hwndParent, handle, cast(POINT*) &rect, 2);
+        RECT headerRect;
+        OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, &headerRect);
+        bool scroll = headerRect.left < rect.left;
+        if (!scroll) {
+            int width = Math.min (rect.right - rect.left, headerRect.right - headerRect.left);
+            scroll = headerRect.left + width > rect.right;
+        }
+        if (scroll) {
+            SCROLLINFO info;
+            info.cbSize = SCROLLINFO.sizeof;
+            info.fMask = OS.SIF_POS;
+            info.nPos = Math.max (0, headerRect.left - Tree.INSET / 2);
+            OS.SetScrollInfo (hwndParent, OS.SB_HORZ, &info, true);
+            setScrollWidth ();
         }
     }
 }
@@ -4993,8 +5299,8 @@
         }
         if ((state & OS.TVIS_SELECTED) is 0) return;
     } else {
-        int oldProc = OS.GetWindowLong (handle, OS.GWL_WNDPROC);
-        OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) TreeProc);
+        int /*long*/ oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC);
+        OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TreeProc);
         TVITEM tvItem_;
         TVITEM* tvItem;
         static if (OS.IsWinCE) {
@@ -5026,7 +5332,7 @@
                 index++;
             }
         }
-        OS.SetWindowLong (handle, OS.GWL_WNDPROC, oldProc);
+        OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc);
     }
     if (hItem !is null) showItem (hItem);
 }
@@ -5061,71 +5367,64 @@
 override void subclass () {
     super.subclass ();
     if (hwndHeader !is null) {
-        OS.SetWindowLong (hwndHeader, OS.GWL_WNDPROC, display.windowProc);
-    }
+        OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, display.windowProc);
+    }
+}
+
+RECT* toolTipInset (RECT* rect) {
+    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+        RECT* insetRect = new RECT();
+        OS.SetRect (insetRect, rect.left - 1, rect.top - 1, rect.right + 1, rect.bottom + 1);
+        return insetRect;
+    }
+    return rect;
+}
+
+RECT* toolTipRect (RECT* rect) {
+    RECT* toolRect = new RECT ();
+    if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+        OS.SetRect (toolRect, rect.left - 1, rect.top - 1, rect.right + 1, rect.bottom + 1);
+    } else {
+        OS.SetRect (toolRect, rect.left, rect.top, rect.right, rect.bottom);
+        int dwStyle = OS.GetWindowLong (itemToolTipHandle, OS.GWL_STYLE);
+        int dwExStyle = OS.GetWindowLong (itemToolTipHandle, OS.GWL_EXSTYLE);
+        OS.AdjustWindowRectEx (toolRect, dwStyle, false, dwExStyle);
+    }
+    return toolRect;
 }
 
 override String toolTipText (NMTTDISPINFO* hdr) {
     auto hwndToolTip = cast(HWND) OS.SendMessage (handle, OS.TVM_GETTOOLTIPS, 0, 0);
     if (hwndToolTip is hdr.hdr.hwndFrom && toolTipText_ !is null) return ""; //$NON-NLS-1$
     if (headerToolTipHandle is hdr.hdr.hwndFrom) {
-        int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-        for (int i=0; i<count; i++) {
+        for (int i=0; i<columnCount; i++) {
             TreeColumn column = columns [i];
             if (column.id is hdr.hdr.idFrom) return column.toolTipText;
         }
         return super.toolTipText (hdr);
     }
-    if (itemToolTipHandle is hdr.hdr.hwndFrom && hwndHeader !is null) {
+    if (itemToolTipHandle is hdr.hdr.hwndFrom) {
         if (toolTipText_ !is null) return "";
-        if (!hooks (DWT.EraseItem) && !hooks (DWT.PaintItem)) {
-            int pos = OS.GetMessagePos ();
-            POINT pt;
-            pt.x = cast(short) (pos & 0xFFFF);
-            pt.y = cast(short) (pos >> 16);
-            OS.ScreenToClient (handle, &pt);
-            TVHITTESTINFO lpht;
-            lpht.pt.x = pt.x;
-            lpht.pt.y = pt.y;
-            OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht);
-            if (lpht.hItem !is null) {
-                auto hDC = OS.GetDC (handle);
-                HFONT oldFont, newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
-                if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
-                RECT rect;
-                OS.GetClientRect (hwndParent, &rect);
-                OS.MapWindowPoints (hwndParent, handle, cast(POINT*) &rect, 2);
-                TreeItem item = _getItem (lpht.hItem);
-                String text = null;
-                int index = 0, count = Math.max (1, OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0));
-                int [] order = new int [count];
-                OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, order.ptr);
-                while (index < count) {
-                    HFONT hFont = item.cellFont !is null ? item.cellFont [order [index]] : cast(HFONT)-1;
-                    if (hFont is cast(HFONT)-1) hFont = item.font;
-                    if (hFont !is cast(HFONT)-1) hFont = OS.SelectObject (hDC, hFont);
-                    RECT cellRect = item.getBounds (order [index], true, false, true, false, true, hDC);
-                    if (hFont !is cast(HFONT)-1) OS.SelectObject (hDC, hFont);
-                    if (cellRect.left > rect.right) break;
-                    cellRect.right = Math.min (cellRect.right, rect.right);
-                    if (OS.PtInRect (&cellRect, pt)) {
-                        RECT textRect = item.getBounds (order [index], true, false, false, false, false, hDC);
-                        if (textRect.right > cellRect.right) {
-                            if (order [index] is 0) {
-                                text = item.text;
-                            } else {
-                                String[] strings = item.strings;
-                                if (strings !is null) text = strings [order [index]];
-                            }
-                        }
-                        break;
-                    }
-                    index++;
-                }
-                if (newFont !is null) OS.SelectObject (hDC, oldFont);
-                OS.ReleaseDC (handle, hDC);
-                if (text !is null) return text;
-            }
+        int pos = OS.GetMessagePos ();
+        POINT pt;
+        OS.POINTSTOPOINT (pt, pos);
+        OS.ScreenToClient (handle, &pt);
+        int index;
+        TreeItem item;
+        RECT cellRect, itemRect;
+        if (findCell (pt.x, pt.y, item, index, cellRect, itemRect)) {
+            String text = null;
+            if (index is 0) {
+                text = item.text;
+            } else {
+                String[] strings = item.strings;
+                if (strings !is null) text = strings [index];
+            }
+            //TEMPORARY CODE
+            if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+                if (isCustomToolTip ()) text = " ";
+            }
+            if (text !is null) return text;
         }
     }
     return super.toolTipText (hdr);
@@ -5164,8 +5463,7 @@
     lpti.uFlags = OS.TTF_SUBCLASS;
     lpti.hwnd = hwndHeader;
     lpti.lpszText = OS.LPSTR_TEXTCALLBACK;
-    int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-    for (int i=0; i<count; i++) {
+    for (int i=0; i<columnCount; i++) {
         TreeColumn column = columns [i];
         if (OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, i, &rect) !is 0) {
             lpti.uId = column.id = display.nextToolTipId++;
@@ -5224,7 +5522,6 @@
 
 void updateScrollBar () {
     if (hwndParent !is null) {
-        int columnCount = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
         if (columnCount !is 0 || scrollWidth !is 0) {
             SCROLLINFO info;
             info.cbSize = SCROLLINFO.sizeof;
@@ -5236,7 +5533,16 @@
                 OS.SetScrollInfo (hwndParent, OS.SB_VERT, &info, true);
             } else {
                 OS.GetScrollInfo (handle, OS.SB_VERT, &info);
-                if (info.nPage is 0) info.nPage = info.nMax + 1;
+                if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION(4, 10)) {
+                    if (info.nPage is 0) {
+                        SCROLLBARINFO psbi;
+                        psbi.cbSize = SCROLLBARINFO.sizeof;
+                        OS.GetScrollBarInfo (handle, OS.OBJID_VSCROLL, &psbi);
+                        if ((psbi.rgstate [0] & OS.STATE_SYSTEM_INVISIBLE) !is 0) {
+                            info.nPage = info.nMax + 1;
+                        }
+                    }
+                }
                 OS.SetScrollInfo (hwndParent, OS.SB_VERT, &info, true);
             }
         }
@@ -5246,13 +5552,13 @@
 override void unsubclass () {
     super.unsubclass ();
     if (hwndHeader !is null) {
-        OS.SetWindowLong (hwndHeader, OS.GWL_WNDPROC, cast(int) HeaderProc);
+        OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, cast(LONG_PTR)HeaderProc);
     }
 }
 
 override int widgetStyle () {
     int bits = super.widgetStyle () | OS.TVS_SHOWSELALWAYS | OS.TVS_LINESATROOT | OS.TVS_HASBUTTONS | OS.TVS_NONEVENHEIGHT;
-    if (EXPLORER_THEME && !OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+    if (EXPLORER_THEME && !OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0) && OS.IsAppThemed ()) {
         bits |= OS.TVS_TRACKSELECT;
         if ((style & DWT.FULL_SELECTION) !is 0) bits |= OS.TVS_FULLROWSELECT;
     } else {
@@ -5262,6 +5568,15 @@
             bits |= OS.TVS_HASLINES;
         }
     }
+    if ((style & (DWT.H_SCROLL | DWT.V_SCROLL)) is 0) {
+        bits &= ~(OS.WS_HSCROLL | OS.WS_VSCROLL);
+        bits |= OS.TVS_NOSCROLL;
+    } else {
+        if ((style & DWT.H_SCROLL) is 0) {
+            bits &= ~OS.WS_HSCROLL;
+            bits |= OS.TVS_NOHSCROLL;
+        }
+    }
 //  bits |= OS.TVS_NOTOOLTIPS | OS.TVS_DISABLEDRAGDROP;
     return bits | OS.TVS_DISABLEDRAGDROP;
 }
@@ -5331,17 +5646,15 @@
             }
             case OS.WM_SETCURSOR: {
                 if (cast(HWND)wParam is hwnd) {
-                    int hitTest = cast(short) (lParam & 0xFFFF);
+                    int hitTest = cast(short) OS.LOWORD (lParam);
                     if (hitTest is OS.HTCLIENT) {
                         HDHITTESTINFO pinfo;
                         int pos = OS.GetMessagePos ();
                         POINT pt;
-                        pt.x = cast(short) (pos & 0xFFFF);
-                        pt.y = cast(short) (pos >> 16);
+                        OS.POINTSTOPOINT (pt, pos);
                         OS.ScreenToClient (hwnd, &pt);
                         pinfo.pt.x = pt.x;
                         pinfo.pt.y = pt.y;
-                        int columnCount = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
                         int index = OS.SendMessage (hwndHeader, OS.HDM_HITTEST, 0, &pinfo);
                         if (0 <= index && index < columnCount && !columns [index].resizable) {
                             if ((pinfo.flags & (OS.HHT_ONDIVIDER | OS.HHT_ONDIVOPEN)) !is 0) {
@@ -5367,7 +5680,7 @@
                 setScrollWidth ();
                 if (ignoreResize) return 0;
                 setResizeChildren (false);
-                int code = callWindowProc (hwnd, OS.WM_SIZE, wParam, lParam);
+                int /*long*/ code = callWindowProc (hwnd, OS.WM_SIZE, wParam, lParam);
                 sendEvent (DWT.Resize);
                 if (isDisposed ()) return 0;
                 if (layout_ !is null) {
@@ -5421,12 +5734,12 @@
                 * on Windows Vista.
                 */
                 if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
-                    if ((wParam & 0xFFFF) is OS.SB_THUMBTRACK) {
+                    if (OS.LOWORD (wParam) is OS.SB_THUMBTRACK) {
                         info.nPos = info.nTrackPos;
                     }
                 }
                 OS.SetScrollInfo (handle, OS.SB_VERT, &info, true);
-                int code = OS.SendMessage (handle, OS.WM_VSCROLL, wParam, lParam);
+                int /*long*/ code = OS.SendMessage (handle, OS.WM_VSCROLL, wParam, lParam);
                 OS.GetScrollInfo (handle, OS.SB_VERT, &info);
                 OS.SetScrollInfo (hwndParent, OS.SB_VERT, &info, true);
                 return code;
@@ -5435,6 +5748,20 @@
         }
         return callWindowProc (hwnd, msg, wParam, lParam);
     }
+    if (msg is Display.DI_GETDRAGIMAGE) {
+        //TEMPORARY CODE
+        if (hooks (DWT.EraseItem) || hooks (DWT.PaintItem)) return 0;
+        /*
+        * When there is more than one item selected, DI_GETDRAGIMAGE
+        * returns the item under the cursor.  This happens because
+        * the tree does not have implement multi-select.  The fix
+        * is to disable DI_GETDRAGIMAGE when more than one item is
+        * selected.
+        */
+        if ((style & DWT.MULTI) !is 0) {
+            if (getSelectionCount () !is 1) return 0;
+        }
+    }
     return super.windowProc (hwnd, msg, wParam, lParam);
 }
 
@@ -5545,7 +5872,29 @@
     return super.WM_GETOBJECT (wParam, lParam);
 }
 
-override LRESULT WM_KEYDOWN (int wParam, int lParam) {
+override LRESULT WM_HSCROLL (int wParam, int lParam) {
+    bool fixScroll = false;
+    if ((style & DWT.DOUBLE_BUFFERED) !is 0) {
+        fixScroll = (style & DWT.VIRTUAL) !is 0 || hooks (DWT.EraseItem) || hooks (DWT.PaintItem);
+    }
+    if (fixScroll) {
+        style &= ~DWT.DOUBLE_BUFFERED;
+        if (explorerTheme) {
+            OS.SendMessage (handle, OS.TVM_SETEXTENDEDSTYLE, OS.TVS_EX_DOUBLEBUFFER, 0);
+        }
+    }
+    LRESULT result = super.WM_HSCROLL (wParam, lParam);
+    if (fixScroll) {
+        style |= DWT.DOUBLE_BUFFERED;
+        if (explorerTheme) {
+            OS.SendMessage (handle, OS.TVM_SETEXTENDEDSTYLE, OS.TVS_EX_DOUBLEBUFFER, OS.TVS_EX_DOUBLEBUFFER);
+        }
+    }
+    if (result !is null) return result;
+    return result;
+}
+
+override LRESULT WM_KEYDOWN (int /*long*/ wParam, int /*long*/ lParam) {
     LRESULT result = super.WM_KEYDOWN (wParam, lParam);
     if (result !is null) return result;
     switch (wParam) {
@@ -5560,10 +5909,9 @@
         case OS.VK_ADD:
             if (OS.GetKeyState (OS.VK_CONTROL) < 0) {
                 if (hwndHeader !is null) {
-                    int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-                    TreeColumn [] newColumns = new TreeColumn [count];
-                    System.arraycopy (columns, 0, newColumns, 0, count);
-                    for (int i=0; i<count; i++) {
+                    TreeColumn [] newColumns = new TreeColumn [columnCount];
+                    System.arraycopy (columns, 0, newColumns, 0, columnCount);
+                    for (int i=0; i<columnCount; i++) {
                         TreeColumn column = newColumns [i];
                         if (!column.isDisposed () && column.getResizable ()) {
                             column.pack ();
@@ -5585,7 +5933,7 @@
                 if (hItem !is null) {
                     if (hAnchor is null) hAnchor = hItem;
                     ignoreSelect = ignoreDeselect = true;
-                    int code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam);
+                    int /*long*/ code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam);
                     ignoreSelect = ignoreDeselect = false;
                     auto hNewItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
                     TVITEM tvItem;
@@ -5593,11 +5941,12 @@
                     tvItem.stateMask = OS.TVIS_SELECTED;
                     auto hDeselectItem = hItem;
                     RECT rect1;
-                    rect1.left = cast(int)hAnchor;
-                    OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect1);
+                    if (!OS.TreeView_GetItemRect (handle, hAnchor, &rect1, false)) {
+                        hAnchor = hItem;
+                        OS.TreeView_GetItemRect (handle, hAnchor, &rect1, false);
+                    }
                     RECT rect2;
-                    rect2.left = cast(int)hDeselectItem;
-                    OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect2);
+                    OS.TreeView_GetItemRect (handle, hDeselectItem, &rect2, false);
                     int flags = rect1.top < rect2.top ? OS.TVGN_PREVIOUSVISIBLE : OS.TVGN_NEXTVISIBLE;
                     while (hDeselectItem !is hAnchor) {
                         tvItem.hItem = hDeselectItem;
@@ -5605,10 +5954,8 @@
                         hDeselectItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, flags, hDeselectItem);
                     }
                     auto hSelectItem = hAnchor;
-                    rect1.left = cast(int)hNewItem;
-                    OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect1);
-                    rect2.left = cast(int)hSelectItem;
-                    OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect2);
+                    OS.TreeView_GetItemRect (handle, hNewItem, &rect1, false);
+                    OS.TreeView_GetItemRect (handle, hSelectItem, &rect2, false);
                     tvItem.state = OS.TVIS_SELECTED;
                     flags = rect1.top < rect2.top ? OS.TVGN_PREVIOUSVISIBLE : OS.TVGN_NEXTVISIBLE;
                     while (hSelectItem !is hNewItem) {
@@ -5661,8 +6008,7 @@
                             do {
                                 auto hVisible = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, hNewItem);
                                 if (hVisible is null) break;
-                                rect.left = cast(int)hVisible;
-                                OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect);
+                                if (!OS.TreeView_GetItemRect (handle, hVisible, &rect, false)) break;
                                 if (rect.bottom > clientRect.bottom) break;
                                 if ((hNewItem = hVisible) is hItem) {
                                     OS.SendMessage (handle, OS.WM_VSCROLL, OS.SB_PAGEDOWN, 0);
@@ -5701,12 +6047,11 @@
                         }
                         if (redraw) {
                             RECT rect1, rect2;
-                            rect1.left = cast(int) hItem;  rect2.left = cast(int) hNewItem;
-                            int fItemRect = (style & DWT.FULL_SELECTION) !is 0 ? 0 : 1;
-                            if (hooks (DWT.EraseItem) || hooks (DWT.PaintItem)) fItemRect = 0;
-                            if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) fItemRect = 0;
-                            OS.SendMessage (handle, OS.TVM_GETITEMRECT, fItemRect, &rect1);
-                            OS.SendMessage (handle, OS.TVM_GETITEMRECT, fItemRect, &rect2);
+                            bool fItemRect = (style & DWT.FULL_SELECTION) is 0;
+                            if (hooks (DWT.EraseItem) || hooks (DWT.PaintItem)) fItemRect = false;
+                            if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) fItemRect = false;
+                            OS.TreeView_GetItemRect (handle, hItem, &rect1, fItemRect);
+                            OS.TreeView_GetItemRect (handle, hNewItem, &rect2, fItemRect);
                             OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
                             OS.InvalidateRect (handle, &rect1, true);
                             OS.InvalidateRect (handle, &rect2, true);
@@ -5716,7 +6061,7 @@
                     }
                 }
             }
-            int code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam);
+            int /*long*/ code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam);
             hAnchor = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
             return new LRESULT (code);
         }
@@ -5757,8 +6102,8 @@
 
 override LRESULT WM_LBUTTONDBLCLK (int wParam, int lParam) {
     TVHITTESTINFO lpht;
-    lpht.pt.x = cast(short) (lParam & 0xFFFF);
-    lpht.pt.y = cast(short) (lParam >> 16);
+    lpht.pt.x = OS.GET_X_LPARAM (lParam);
+    lpht.pt.y = OS.GET_Y_LPARAM (lParam);
     OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht);
     if (lpht.hItem !is null) {
         if ((style & DWT.CHECK) !is 0) {
@@ -5807,7 +6152,18 @@
     LRESULT result = super.WM_LBUTTONDBLCLK (wParam, lParam);
     if (result is LRESULT.ZERO) return result;
     if (lpht.hItem !is null) {
-        if ((style & DWT.FULL_SELECTION) !is 0 || (lpht.flags & OS.TVHT_ONITEM) !is 0) {
+        int flags = OS.TVHT_ONITEM;
+        if ((style & DWT.FULL_SELECTION) !is 0) {
+            flags |= OS.TVHT_ONITEMRIGHT | OS.TVHT_ONITEMINDENT;
+        } else {
+            if (hooks (DWT.MeasureItem)) {
+                lpht.flags &= ~(OS.TVHT_ONITEMICON | OS.TVHT_ONITEMLABEL);
+                if (hitTestSelection (lpht.hItem, lpht.pt.x, lpht.pt.y)) {
+                    lpht.flags |= OS.TVHT_ONITEMICON | OS.TVHT_ONITEMLABEL;
+                }
+            }
+        }
+        if ((lpht.flags & flags) !is 0) {
             Event event = new Event ();
             event.item = _getItem (lpht.hItem);
             postEvent (DWT.DefaultSelection, event);
@@ -5825,8 +6181,8 @@
     * below the last item is selected.
     */
     TVHITTESTINFO lpht;
-    lpht.pt.x = cast(short) (lParam & 0xFFFF);
-    lpht.pt.y = cast(short) (lParam >> 16);
+    lpht.pt.x = OS.GET_X_LPARAM (lParam);
+    lpht.pt.y = OS.GET_Y_LPARAM (lParam);
     OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht);
     if (lpht.hItem is null || (lpht.flags & OS.TVHT_ONITEMBUTTON) !is 0) {
         Display display = this.display;
@@ -5838,9 +6194,9 @@
             return LRESULT.ZERO;
         }
         bool fixSelection = false, deselected = false;
+        HANDLE hOldSelection = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
         if (lpht.hItem !is null && (style & DWT.MULTI) !is 0) {
-            int hSelection = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
-            if (hSelection !is 0) {
+            if (hOldSelection !is null) {
                 TVITEM tvItem;
                 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
                 tvItem.hItem = lpht.hItem;
@@ -5850,6 +6206,7 @@
                     tvItem.stateMask = OS.TVIS_SELECTED;
                     auto hNext = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, lpht.hItem);
                     while (hNext !is null) {
+                        if (hNext is hAnchor) hAnchor = null;
                         tvItem.hItem = hNext;
                         OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem);
                         if ((tvItem.state & OS.TVIS_SELECTED) !is 0) deselected = true;
@@ -5866,13 +6223,39 @@
         }
         dragStarted = gestureCompleted = false;
         if (fixSelection) ignoreDeselect = ignoreSelect = lockSelection = true;
-        int code = callWindowProc (handle, OS.WM_LBUTTONDOWN, wParam, lParam);
+        int /*long*/ code = callWindowProc (handle, OS.WM_LBUTTONDOWN, wParam, lParam);
         if (fixSelection) ignoreDeselect = ignoreSelect = lockSelection = false;
+        HANDLE hNewSelection = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+        if (hOldSelection !is hNewSelection) hAnchor = hNewSelection;
         if (dragStarted) {
             if (!display.captureChanged && !isDisposed ()) {
                 if (OS.GetCapture () !is handle) OS.SetCapture (handle);
             }
         }
+        /*
+        * Bug in Windows.  When a tree has no images and an item is
+        * expanded or collapsed, for some reason, Windows changes
+        * the size of the selection.  When the user expands a tree
+        * item, the selection rectangle is made a few pixels larger.
+        * When the user collapses an item, the selection rectangle
+        * is restored to the original size but the selection is not
+        * redrawn, causing pixel corruption.  The fix is to detect
+        * this case and redraw the item.
+        */
+        if ((lpht.flags & OS.TVHT_ONITEMBUTTON) !is 0) {
+            int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+            if ((bits & OS.TVS_FULLROWSELECT) is 0) {
+                if (OS.SendMessage (handle, OS.TVM_GETIMAGELIST, OS.TVSIL_NORMAL, 0) is 0) {
+                    auto hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+                    if (hItem !is null) {
+                        RECT rect;
+                        if (OS.TreeView_GetItemRect (handle, hItem, &rect, false)) {
+                            OS.InvalidateRect (handle, &rect, true);
+                        }
+                    }
+                }
+            }
+        }
         if (deselected) {
             Event event = new Event ();
             event.item = _getItem (lpht.hItem);
@@ -5924,8 +6307,31 @@
         }
     }
 
+    /*
+    * Feature in Windows.  When the tree has the style
+    * TVS_FULLROWSELECT, the background color for the
+    * entire row is filled when an item is painted,
+    * drawing on top of any custom drawing.  The fix
+    * is to emulate TVS_FULLROWSELECT.
+    */
+    bool selected = false;
+    bool fakeSelection = false;
+    if (lpht.hItem !is null) {
+        if ((style & DWT.FULL_SELECTION) !is 0) {
+            int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+            if ((bits & OS.TVS_FULLROWSELECT) is 0) fakeSelection = true;
+        } else {
+            if (hooks (DWT.MeasureItem)) {
+                selected = hitTestSelection (lpht.hItem, lpht.pt.x, lpht.pt.y) !is 0;
+                if (selected) {
+                    if ((lpht.flags & OS.TVHT_ONITEM) is 0) fakeSelection = true;
+                }
+            }
+        }
+    }
+
     /* Process the mouse when an item is not selected */
-    if ((style & DWT.FULL_SELECTION) is 0) {
+    if (!selected && (style & DWT.FULL_SELECTION) is 0) {
         if ((lpht.flags & OS.TVHT_ONITEM) is 0) {
             Display display = this.display;
             display.captureChanged = false;
@@ -5935,7 +6341,7 @@
                 }
                 return LRESULT.ZERO;
             }
-            int code = callWindowProc (handle, OS.WM_LBUTTONDOWN, wParam, lParam);
+            int /*long*/ code = callWindowProc (handle, OS.WM_LBUTTONDOWN, wParam, lParam);
             if (!display.captureChanged && !isDisposed ()) {
                 if (OS.GetCapture () !is handle) OS.SetCapture (handle);
             }
@@ -5947,16 +6353,14 @@
     TVITEM tvItem;
     tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
     tvItem.stateMask = OS.TVIS_SELECTED;
-    bool hittestSelected = false, focused = false;
+    bool hittestSelected = false;
     if ((style & DWT.MULTI) !is 0) {
         tvItem.hItem = lpht.hItem;
         OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem);
         hittestSelected = (tvItem.state & OS.TVIS_SELECTED) !is 0;
-        focused = OS.GetFocus () is handle;
     }
 
     /* Get the selected state of the last selected item */
-    bool redraw = false;
     auto hOldItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
     if ((style & DWT.MULTI) !is 0) {
         tvItem.hItem = hOldItem;
@@ -5966,8 +6370,8 @@
         if (hittestSelected || (wParam & OS.MK_CONTROL) !is 0) {
             /*
             * Feature in Windows.  When the tree is not drawing focus
-            * and the user selects a tree item using while the CONTROL
-            * key is down, the tree window proc sends WM_UPDATEUISTATE
+            * and the user selects a tree item while the CONTROL key
+            * is down, the tree window proc sends WM_UPDATEUISTATE
             * to the top level window, causing controls within the shell
             * to redraw.  When drag detect is enabled, the tree window
             * proc runs a modal loop that allows WM_PAINT messages to be
@@ -5978,23 +6382,21 @@
             * on without redrawing the entire tree, pixel corruption occurs.
             * This case only seems to happen when the tree has been given
             * focus from WM_MOUSEACTIVATE of the shell.  The fix is to
-            * detect that WM_UPDATEUISTATE will be sent and avoid using
-            * WM_SETREDRAW to disable drawing.
+            * force the WM_UPDATEUISTATE to be sent before disabling
+            * the drawing.
             *
             * NOTE:  Any redraw of a parent (or sibling) will be dispatched
             * during the modal drag detect loop.  This code only fixes the
             * case where the tree causes a redraw from WM_UPDATEUISTATE.
-            * In DWT, the InvalidateRect() that causes the pixel corruption
+            * In DWT, the InvalidateRect() that caused the pixel corruption
             * is found in Composite.WM_UPDATEUISTATE().
             */
             int uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
-            if ((uiState & OS.UISF_HIDEFOCUS) is 0) {
-                redraw = focused && drawCount is 0 && OS.IsWindowVisible (handle);
-            }
-            if (redraw) {
-                OS.UpdateWindow (handle);
-                OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
-            }
+            if ((uiState & OS.UISF_HIDEFOCUS) !is 0) {
+                OS.SendMessage (handle, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0);
+            }
+            OS.UpdateWindow (handle);
+            OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0);
         } else {
             deselectAll ();
         }
@@ -6012,25 +6414,15 @@
     hSelect = lpht.hItem;
     dragStarted = gestureCompleted = false;
     ignoreDeselect = ignoreSelect = true;
-    int code = callWindowProc (handle, OS.WM_LBUTTONDOWN, wParam, lParam);
+    int /*long*/ code = callWindowProc (handle, OS.WM_LBUTTONDOWN, wParam, lParam);
     auto hNewItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
-    /*
-    * Feature in Windows.  When the tree has the style
-    * TVS_FULLROWSELECT, the background color for the
-    * entire row is filled when an item is painted,
-    * drawing on top of any custom drawing.  The fix
-    * is to emulate TVS_FULLROWSELECT.
-    */
-    if ((style & DWT.FULL_SELECTION) !is 0) {
-        int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
-        if ((bits & OS.TVS_FULLROWSELECT) is 0) {
-            if (hNewItem is hOldItem && lpht.hItem !is hOldItem) {
-                OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_CARET, lpht.hItem);
-                hNewItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
-            }
-            if (!dragStarted && lpht.hItem !is null && (state & DRAG_DETECT) !is 0 && hooks (DWT.DragDetect)) {
-                dragStarted = dragDetect (handle, lpht.pt.x, lpht.pt.y, false, null, null);
-            }
+    if (fakeSelection) {
+        if (hOldItem is null || (hNewItem is hOldItem && lpht.hItem !is hOldItem)) {
+            OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_CARET, lpht.hItem);
+            hNewItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0);
+        }
+        if (!dragStarted && (state & DRAG_DETECT) !is 0 && hooks (DWT.DragDetect)) {
+            dragStarted = dragDetect (handle, lpht.pt.x, lpht.pt.y, false, null, null);
         }
     }
     ignoreDeselect = ignoreSelect = false;
@@ -6083,27 +6475,24 @@
                     }
                 }
             }
-            if (redraw) {
-                RECT rect1, rect2;
-                rect1.left = cast(int) hOldItem;  rect2.left = cast(int) hNewItem;
-                int fItemRect = (style & DWT.FULL_SELECTION) !is 0 ? 0 : 1;
-                if (hooks (DWT.EraseItem) || hooks (DWT.PaintItem)) fItemRect = 0;
-                if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) fItemRect = 0;
-                OS.SendMessage (handle, OS.TVM_GETITEMRECT, fItemRect, &rect1);
-                OS.SendMessage (handle, OS.TVM_GETITEMRECT, fItemRect, &rect2);
-                OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
-                OS.InvalidateRect (handle, &rect1, true);
-                OS.InvalidateRect (handle, &rect2, true);
-                OS.UpdateWindow (handle);
-            }
+            RECT rect1, rect2;
+            bool fItemRect = (style & DWT.FULL_SELECTION) is 0;
+            if (hooks (DWT.EraseItem) || hooks (DWT.PaintItem)) fItemRect = false;
+            if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) fItemRect = false;
+            OS.TreeView_GetItemRect (handle, hOldItem, &rect1, fItemRect);
+            OS.TreeView_GetItemRect (handle, hNewItem, &rect2, fItemRect);
+            OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+            OS.InvalidateRect (handle, &rect1, true);
+            OS.InvalidateRect (handle, &rect2, true);
+            OS.UpdateWindow (handle);
         }
 
         /* Check for SHIFT or normal select and deselect/reselect items */
         if ((wParam & OS.MK_CONTROL) is 0) {
             if (!hittestSelected || !dragStarted) {
                 tvItem.state = 0;
-                int oldProc = OS.GetWindowLong (handle, OS.GWL_WNDPROC);
-                OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) TreeProc);
+                auto oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC);
+                OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TreeProc);
                 if ((style & DWT.VIRTUAL) !is 0) {
                     HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0);
                     deselect (hItem, &tvItem, hNewItem);
@@ -6119,23 +6508,22 @@
                 tvItem.hItem = hNewItem;
                 tvItem.state = OS.TVIS_SELECTED;
                 OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
-                OS.SetWindowLong (handle, OS.GWL_WNDPROC, oldProc);
+                OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc);
                 if ((wParam & OS.MK_SHIFT) !is 0) {
                     RECT rect1;
                     if (hAnchor is null) hAnchor = hNewItem;
-                    rect1.left = cast(int) hAnchor;
-                    if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect1) !is 0) {
+                    if (OS.TreeView_GetItemRect (handle, hAnchor, &rect1, false)) {
                         RECT rect2;
-                        rect2.left = cast(int) hNewItem;
-                        OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect2);
-                        int flags = rect1.top < rect2.top ? OS.TVGN_NEXTVISIBLE : OS.TVGN_PREVIOUSVISIBLE;
-                        tvItem.state = OS.TVIS_SELECTED;
-                        auto hItem = tvItem.hItem = hAnchor;
-                        OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
-                        while (hItem !is hNewItem) {
-                            tvItem.hItem = hItem;
+                        if (OS.TreeView_GetItemRect (handle, hNewItem, &rect2, false)) {
+                            int flags = rect1.top < rect2.top ? OS.TVGN_NEXTVISIBLE : OS.TVGN_PREVIOUSVISIBLE;
+                            tvItem.state = OS.TVIS_SELECTED;
+                            auto hItem = tvItem.hItem = hAnchor;
                             OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
-                            hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, flags, hItem);
+                            while (hItem !is hNewItem) {
+                                tvItem.hItem = hItem;
+                                OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
+                                hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, flags, hItem);
+                            }
                         }
                     }
                 }
@@ -6164,7 +6552,7 @@
     * issue a fake mouse up.
     */
     if (dragStarted) {
-        sendDragEvent (1, cast(short) (lParam & 0xFFFF), cast(short) (lParam >> 16));
+        sendDragEvent (1, OS.GET_X_LPARAM (lParam), OS.GET_Y_LPARAM (lParam));
     } else {
         int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
         if ((bits & OS.TVS_DISABLEDRAGDROP) is 0) {
@@ -6179,7 +6567,7 @@
     Display display = this.display;
     LRESULT result = super.WM_MOUSEMOVE (wParam, lParam);
     if (result !is null) return result;
-    if (itemToolTipHandle !is null && hwndHeader !is null) {
+    if (itemToolTipHandle !is null) {
         /*
         * Bug in Windows.  On some machines that do not have XBUTTONs,
         * the MK_XBUTTON1 and OS.MK_XBUTTON2 bits are sometimes set,
@@ -6188,53 +6576,36 @@
         */
         int mask = OS.MK_LBUTTON | OS.MK_MBUTTON | OS.MK_RBUTTON;
         if (display.xMouse) mask |= OS.MK_XBUTTON1 | OS.MK_XBUTTON2;
-        if (((wParam & 0xFFFF) & mask) is 0) {
-            TVHITTESTINFO lpht;
-            lpht.pt.x = cast(short) (lParam & 0xFFFF);
-            lpht.pt.y = cast(short) (lParam >> 16);
-            OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht);
-            if (lpht.hItem !is null) {
-                auto hDC = OS.GetDC (handle);
-                HFONT oldFont, newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
-                if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
-                POINT pt;
-                pt.x = lpht.pt.x;
-                pt.y = lpht.pt.y;
-                RECT rect;
-                OS.GetClientRect (hwndParent, &rect);
-                OS.MapWindowPoints (hwndParent, handle, cast(POINT*) &rect, 2);
-                TreeItem item = _getItem (lpht.hItem);
-                int index = 0, count = Math.max (1, OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0));
-                int [] order = new int [count];
-                OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, order.ptr);
-                while (index < count) {
-                    HFONT hFont = item.cellFont !is null ? item.cellFont [order [index]] : cast(HFONT)-1;
-                    if (hFont is cast(HFONT)-1) hFont = item.font;
-                    if (hFont !is cast(HFONT)-1) hFont = OS.SelectObject (hDC, hFont);
-                    RECT cellRect = item.getBounds (order [index], true, false, true, false, true, hDC);
-                    if (hFont !is cast(HFONT)-1) OS.SelectObject (hDC, hFont);
-                    if (cellRect.left > rect.right) break;
-                    cellRect.right = Math.min (cellRect.right, rect.right);
-                    if (OS.PtInRect (&cellRect, pt)) {
-                        RECT textRect = item.getBounds (order [index], true, false, false, false, false, hDC);
-                        if (textRect.right > cellRect.right) {
-                            TOOLINFO lpti;
-                            lpti.cbSize = TOOLINFO.sizeof;
-                            lpti.hwnd = handle;
-                            lpti.uId = cast(int) handle;
-                            lpti.uFlags = OS.TTF_SUBCLASS | OS.TTF_TRANSPARENT;
-                            lpti.rect.left = cellRect.left;
-                            lpti.rect.top = cellRect.top;
-                            lpti.rect.right = cellRect.right;
-                            lpti.rect.bottom = cellRect.bottom;
-                            OS.SendMessage (itemToolTipHandle, OS.TTM_NEWTOOLRECT, 0, &lpti);
-                        }
-                        break;
+        if ((wParam & mask) is 0) {
+            int x = OS.GET_X_LPARAM (lParam);
+            int y = OS.GET_Y_LPARAM (lParam);
+            int index;
+            TreeItem item;
+            RECT cellRect, itemRect;
+            if (findCell (x, y, item, index, cellRect, itemRect)) {
+                /*
+                * Feature in Windows.  When the new tool rectangle is
+                * set using TTM_NEWTOOLRECT and the tooltip is visible,
+                * Windows draws the tooltip right away and the sends
+                * WM_NOTIFY with TTN_SHOW.  This means that the tooltip
+                * shows first at the wrong location and then moves to
+                * the right one.  The fix is to hide the tooltip window.
+                */
+                if (OS.SendMessage (itemToolTipHandle, OS.TTM_GETCURRENTTOOL, 0, 0) is 0) {
+                    if (OS.IsWindowVisible (itemToolTipHandle)) {
+                        OS.ShowWindow (itemToolTipHandle, OS.SW_HIDE);
                     }
-                    index++;
                 }
-                if (newFont !is null) OS.SelectObject (hDC, oldFont);
-                OS.ReleaseDC (handle, hDC);
+                TOOLINFO lpti;
+                lpti.cbSize = TOOLINFO.sizeof;
+                lpti.hwnd = handle;
+                lpti.uId = cast(int) handle;
+                lpti.uFlags = OS.TTF_SUBCLASS | OS.TTF_TRANSPARENT;
+                lpti.rect.left = cellRect.left;
+                lpti.rect.top = cellRect.top;
+                lpti.rect.right = cellRect.right;
+                lpti.rect.bottom = cellRect.bottom;
+                OS.SendMessage (itemToolTipHandle, OS.TTM_NEWTOOLRECT, 0, &lpti);
             }
         }
     }
@@ -6283,12 +6654,20 @@
     * This behavior is consistent with the table.
     */
     TVHITTESTINFO lpht;
-    lpht.pt.x = cast(short) (lParam & 0xFFFF);
-    lpht.pt.y = cast(short) (lParam >> 16);
+    lpht.pt.x = OS.GET_X_LPARAM (lParam);
+    lpht.pt.y = OS.GET_Y_LPARAM (lParam);
     OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht);
     if (lpht.hItem !is null) {
-        int flags = OS.TVHT_ONITEMICON | OS.TVHT_ONITEMLABEL;
-        if ((style & DWT.FULL_SELECTION) !is 0 || (lpht.flags & flags) !is 0) {
+        bool fakeSelection = (style & DWT.FULL_SELECTION) !is 0;
+        if (!fakeSelection) {
+            if (hooks (DWT.MeasureItem)) {
+                fakeSelection = hitTestSelection (lpht.hItem, lpht.pt.x, lpht.pt.y);
+            } else {
+                int flags = OS.TVHT_ONITEMICON | OS.TVHT_ONITEMLABEL;
+                fakeSelection = (lpht.flags & flags) !is 0;
+            }
+        }
+        if (fakeSelection) {
             if ((wParam & (OS.MK_CONTROL | OS.MK_SHIFT)) is 0) {
                 TVITEM tvItem;
                 tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
@@ -6326,11 +6705,9 @@
     }
     if ((style & DWT.DOUBLE_BUFFERED) !is 0 || findImageControl () !is null) {
         bool doubleBuffer = true;
-        if (EXPLORER_THEME) {
-            if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
-                int exStyle = OS.SendMessage (handle, OS.TVM_GETEXTENDEDSTYLE, 0, 0);
-                if ((exStyle & OS.TVS_EX_DOUBLEBUFFER) !is 0) doubleBuffer = false;
-            }
+        if (explorerTheme) {
+            int exStyle = OS.SendMessage (handle, OS.TVM_GETEXTENDEDSTYLE, 0, 0);
+            if ((exStyle & OS.TVS_EX_DOUBLEBUFFER) !is 0) doubleBuffer = false;
         }
         if (doubleBuffer) {
             GC gc = null;
@@ -6402,7 +6779,7 @@
     * is happening in WM_PRINTCLIENT, the redrawing is not visible.
     */
     printClient = true;
-    int code = callWindowProc (handle, OS.WM_PRINTCLIENT, wParam, lParam);
+    int /*long*/ code = callWindowProc (handle, OS.WM_PRINTCLIENT, wParam, lParam);
     printClient = false;
     return new LRESULT (code);
 }
@@ -6475,7 +6852,7 @@
     * Windows Vista running under the theme manager.
     */
     if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
-        int code = OS.DefWindowProc (handle, OS.WM_SETREDRAW, wParam, lParam);
+        int /*long*/ code = OS.DefWindowProc (handle, OS.WM_SETREDRAW, wParam, lParam);
         return code is 0 ? LRESULT.ZERO : new LRESULT (code);
     }
     return result;
@@ -6499,12 +6876,8 @@
     * of the selected items is not drawn.  The fix is the
     * redraw the entire tree.
     */
-    if (EXPLORER_THEME) {
-        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
-            if ((style & DWT.FULL_SELECTION) !is 0) {
-                OS.InvalidateRect (handle, null, false);
-            }
-        }
+    if (explorerTheme && (style & DWT.FULL_SELECTION) !is 0) {
+        OS.InvalidateRect (handle, null, false);
     }
     if (ignoreResize) return null;
     return super.WM_SIZE (wParam, lParam);
@@ -6526,6 +6899,38 @@
     return result;
 }
 
+override LRESULT WM_VSCROLL (int /*long*/ wParam, int /*long*/ lParam) {
+    bool fixScroll = false;
+    if ((style & DWT.DOUBLE_BUFFERED) !is 0) {
+        int code = OS.LOWORD (wParam);
+        switch (code) {
+            case OS.SB_TOP:
+            case OS.SB_BOTTOM:
+            case OS.SB_LINEDOWN:
+            case OS.SB_LINEUP:
+            case OS.SB_PAGEDOWN:
+            case OS.SB_PAGEUP:
+                fixScroll = (style & DWT.VIRTUAL) !is 0 || hooks (DWT.EraseItem) || hooks (DWT.PaintItem);
+                break;
+        }
+    }
+    if (fixScroll) {
+        style &= ~DWT.DOUBLE_BUFFERED;
+        if (explorerTheme) {
+            OS.SendMessage (handle, OS.TVM_SETEXTENDEDSTYLE, OS.TVS_EX_DOUBLEBUFFER, 0);
+        }
+    }
+    LRESULT result = super.WM_VSCROLL (wParam, lParam);
+    if (fixScroll) {
+        style |= DWT.DOUBLE_BUFFERED;
+        if (explorerTheme) {
+            OS.SendMessage (handle, OS.TVM_SETEXTENDEDSTYLE, OS.TVS_EX_DOUBLEBUFFER, OS.TVS_EX_DOUBLEBUFFER);
+        }
+    }
+    if (result !is null) return result;
+    return result;
+}
+
 override LRESULT wmColorChild (int wParam, int lParam) {
     if (findImageControl () !is null) {
         if (OS.COMCTL32_MAJOR < 6) {
@@ -6544,274 +6949,13 @@
 }
 
 override LRESULT wmNotify (NMHDR* hdr, int wParam, int lParam) {
-    if (hdr.hwndFrom is itemToolTipHandle && hwndHeader !is null) {
-        static if (!OS.IsWinCE) {
-            switch (hdr.code) {
-                case OS.TTN_POP: {
-                    if (display.isXMouseActive ()) {
-                        Shell shell = getShell ();
-                        shell.lockToolTipControl = null;
-                    }
-                    break;
-                }
-                case OS.TTN_SHOW: {
-                    if (display.isXMouseActive ()) {
-                        Shell shell = getShell ();
-                        shell.lockToolTipControl = this;
-                    }
-                    int pos = OS.GetMessagePos ();
-                    POINT pt;
-                    pt.x = cast(short) (pos & 0xFFFF);
-                    pt.y = cast(short) (pos >> 16);
-                    OS.ScreenToClient (handle, &pt);
-                    TVHITTESTINFO lpht;
-                    lpht.pt.x = pt.x;
-                    lpht.pt.y = pt.y;
-                    OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht);
-                    if (lpht.hItem !is null) {
-                        auto hDC = OS.GetDC (handle);
-                        HFONT oldFont, newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
-                        if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont);
-                        LRESULT result = null;
-                        RECT rect;
-                        OS.GetClientRect (hwndParent, &rect);
-                        OS.MapWindowPoints (hwndParent, handle, cast(POINT*) &rect, 2);
-                        TreeItem item = _getItem (lpht.hItem);
-                        int index = 0, count = Math.max (1, OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0));
-                        int [] order = new int [count];
-                        OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, order.ptr);
-                        while (index < count) {
-                            HFONT hFont = item.cellFont !is null ? item.cellFont [order [index]] : cast(HFONT)-1;
-                            if (hFont is cast(HFONT)-1) hFont = item.font;
-                            if (hFont !is cast(HFONT)-1) hFont = OS.SelectObject (hDC, hFont);
-                            RECT cellRect = item.getBounds (order [index], true, false, true, false, true, hDC);
-                            if (hFont !is cast(HFONT)-1) OS.SelectObject (hDC, hFont);
-                            if (cellRect.left > rect.right) break;
-                            cellRect.right = Math.min (cellRect.right, rect.right);
-                            if (OS.PtInRect (&cellRect, pt)) {
-                                RECT textRect = item.getBounds (order [index], true, false, false, false, false, hDC);
-                                if (textRect.right > cellRect.right) {
-                                    OS.MapWindowPoints (handle, null, cast(POINT*) &textRect, 2);
-                                    int flags = OS.SWP_NOACTIVATE | OS.SWP_NOSIZE | OS.SWP_NOZORDER;
-                                    SetWindowPos (itemToolTipHandle, null, textRect.left, textRect.top, 0, 0, flags);
-                                    result = LRESULT.ONE;
-                                }
-                                break;
-                            }
-                            index++;
-                        }
-                        if (newFont !is null) OS.SelectObject (hDC, oldFont);
-                        OS.ReleaseDC (handle, hDC);
-                        if (result !is null) return result;
-                    }
-                }
-                default:
-            }
-        }
+    if (hdr.hwndFrom is itemToolTipHandle) {
+        LRESULT result = wmNotifyToolTip (hdr, wParam, lParam);
+        if (result !is null) return result;
     }
     if (hdr.hwndFrom is hwndHeader) {
-        /*
-        * Feature in Windows.  On NT, the automatically created
-        * header control is created as a UNICODE window, not an
-        * ANSI window despite the fact that the parent is created
-        * as an ANSI window.  This means that it sends UNICODE
-        * notification messages to the parent window on NT for
-        * no good reason.  The data and size in the NMHEADER and
-        * HDITEM structs is identical between the platforms so no
-        * different message is actually necessary.  Despite this,
-        * Windows sends different messages.  The fix is to look
-        * for both messages, despite the platform.  This works
-        * because only one will be sent on either platform, never
-        * both.
-        */
-        switch (hdr.code) {
-            case OS.HDN_BEGINTRACKW:
-            case OS.HDN_BEGINTRACKA:
-            case OS.HDN_DIVIDERDBLCLICKW:
-            case OS.HDN_DIVIDERDBLCLICKA: {
-                NMHEADER* phdn = cast(NMHEADER*)lParam;
-                //OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
-                TreeColumn column = columns [phdn.iItem];
-                if (column !is null && !column.getResizable ()) {
-                    return LRESULT.ONE;
-                }
-                ignoreColumnMove = true;
-                switch (hdr.code) {
-                    case OS.HDN_DIVIDERDBLCLICKW:
-                    case OS.HDN_DIVIDERDBLCLICKA:
-                        if (column !is null) column.pack ();
-                    default:
-                }
-                break;
-            }
-            case OS.NM_RELEASEDCAPTURE: {
-                if (!ignoreColumnMove) {
-                    int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-                    for (int i=0; i<count; i++) {
-                        TreeColumn column = columns [i];
-                        column.updateToolTip (i);
-                    }
-                    updateImageList ();
-                }
-                ignoreColumnMove = false;
-                break;
-            }
-            case OS.HDN_BEGINDRAG: {
-                if (ignoreColumnMove) return LRESULT.ONE;
-                NMHEADER* phdn = cast(NMHEADER*)lParam;
-                //OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
-                if (phdn.iItem !is -1) {
-                    TreeColumn column = columns [phdn.iItem];
-                    if (column !is null && !column.getMoveable ()) {
-                        ignoreColumnMove = true;
-                        return LRESULT.ONE;
-                    }
-                }
-                break;
-            }
-            case OS.HDN_ENDDRAG: {
-                NMHEADER* phdn = cast(NMHEADER*)lParam;
-                //OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
-                if (phdn.iItem !is -1 && phdn.pitem !is null) {
-                    HDITEM* pitem = phdn.pitem;
-                    //OS.MoveMemory (pitem, phdn.pitem, HDITEM.sizeof);
-                    if ((pitem.mask & OS.HDI_ORDER) !is 0 && pitem.iOrder !is -1) {
-                        int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-                        int [] order = new int [count];
-                        OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, order.ptr);
-                        int index = 0;
-                        while (index < order.length) {
-                            if (order [index] is phdn.iItem) break;
-                            index++;
-                        }
-                        if (index is order.length) index = 0;
-                        if (index is pitem.iOrder) break;
-                        int start = Math.min (index, pitem.iOrder);
-                        int end = Math.max (index, pitem.iOrder);
-                        RECT rect, headerRect;
-                        OS.GetClientRect (handle, &rect);
-                        OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, order [start], &headerRect);
-                        rect.left = Math.max (rect.left, headerRect.left);
-                        OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, order [end], &headerRect);
-                        rect.right = Math.min (rect.right, headerRect.right);
-                        OS.InvalidateRect (handle, &rect, true);
-                        ignoreColumnMove = false;
-                        for (int i=start; i<=end; i++) {
-                            TreeColumn column = columns [order [i]];
-                            if (!column.isDisposed ()) {
-                                column.postEvent (DWT.Move);
-                            }
-                        }
-                    }
-                }
-                break;
-            }
-            case OS.HDN_ITEMCHANGINGW:
-            case OS.HDN_ITEMCHANGINGA: {
-                NMHEADER* phdn = cast(NMHEADER*)lParam;
-                //OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
-                if (phdn.pitem !is null) {
-                    HDITEM* newItem = phdn.pitem;
-                    //OS.MoveMemory (newItem, phdn.pitem, HDITEM.sizeof);
-                    if ((newItem.mask & OS.HDI_WIDTH) !is 0) {
-                        RECT rect;
-                        OS.GetClientRect (handle, &rect);
-                        HDITEM oldItem;
-                        oldItem.mask = OS.HDI_WIDTH;
-                        OS.SendMessage (hwndHeader, OS.HDM_GETITEM, phdn.iItem, &oldItem);
-                        int deltaX = newItem.cxy - oldItem.cxy;
-                        RECT headerRect;
-                        OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, phdn.iItem, &headerRect);
-                        int gridWidth = linesVisible ? GRID_WIDTH : 0;
-                        rect.left = headerRect.right - gridWidth;
-                        int newX = rect.left + deltaX;
-                        rect.right = Math.max (rect.right, rect.left + Math.abs (deltaX));
-                        if (explorerTheme || (findImageControl () !is null || hooks (DWT.EraseItem) || hooks (DWT.PaintItem))) {
-                            OS.InvalidateRect (handle, &rect, true);
-                            OS.OffsetRect (&rect, deltaX, 0);
-                            OS.InvalidateRect (handle, &rect, true);
-                        } else {
-                            int flags = OS.SW_INVALIDATE | OS.SW_ERASE;
-                            OS.ScrollWindowEx (handle, deltaX, 0, &rect, null, null, null, flags);
-                        }
-                        if (OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, phdn.iItem, 0) !is 0) {
-                            rect.left = headerRect.left;
-                            rect.right = newX;
-                            OS.InvalidateRect (handle, &rect, true);
-                        }
-                        setScrollWidth ();
-                    }
-                }
-                break;
-            }
-            case OS.HDN_ITEMCHANGEDW:
-            case OS.HDN_ITEMCHANGEDA: {
-                NMHEADER* phdn = cast(NMHEADER*)lParam;
-                //OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
-                if (phdn.pitem !is null) {
-                    HDITEM* pitem = phdn.pitem;
-                    //OS.MoveMemory (pitem, phdn.pitem, HDITEM.sizeof);
-                    if ((pitem.mask & OS.HDI_WIDTH) !is 0) {
-                        if (ignoreColumnMove) {
-                            if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
-                                int flags = OS.RDW_UPDATENOW | OS.RDW_ALLCHILDREN;
-                                OS.RedrawWindow (handle, null, null, flags);
-                            } else {
-                                if ((style & DWT.DOUBLE_BUFFERED) is 0) {
-                                    int oldStyle = style;
-                                    style |= DWT.DOUBLE_BUFFERED;
-                                    OS.UpdateWindow (handle);
-                                    style = oldStyle;
-                                }
-                            }
-                        }
-                        TreeColumn column = columns [phdn.iItem];
-                        if (column !is null) {
-                            column.updateToolTip (phdn.iItem);
-                            column.sendEvent (DWT.Resize);
-                            if (isDisposed ()) return LRESULT.ZERO;
-                            int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
-                            TreeColumn [] newColumns = new TreeColumn [count];
-                            System.arraycopy (columns, 0, newColumns, 0, count);
-                            int [] order = new int [count];
-                            OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, order.ptr);
-                            bool moved = false;
-                            for (int i=0; i<count; i++) {
-                                TreeColumn nextColumn = newColumns [order [i]];
-                                if (moved && !nextColumn.isDisposed ()) {
-                                    nextColumn.updateToolTip (order [i]);
-                                    nextColumn.sendEvent (DWT.Move);
-                                }
-                                if (nextColumn is column) moved = true;
-                            }
-                        }
-                    }
-                    setScrollWidth ();
-                }
-                break;
-            }
-            case OS.HDN_ITEMCLICKW:
-            case OS.HDN_ITEMCLICKA: {
-                NMHEADER* phdn = cast(NMHEADER*)lParam;
-                //OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
-                TreeColumn column = columns [phdn.iItem];
-                if (column !is null) {
-                    column.postEvent (DWT.Selection);
-                }
-                break;
-            }
-            case OS.HDN_ITEMDBLCLICKW:
-            case OS.HDN_ITEMDBLCLICKA: {
-                NMHEADER* phdn = cast(NMHEADER*)lParam;
-                //OS.MoveMemory (phdn, lParam, NMHEADER.sizeof);
-                TreeColumn column = columns [phdn.iItem];
-                if (column !is null) {
-                    column.postEvent (DWT.DefaultSelection);
-                }
-                break;
-            }
-            default:
-        }
+        LRESULT result = wmNotifyHeader (hdr, wParam, lParam);
+        if (result !is null) return result;
     }
     return super.wmNotify (hdr, wParam, lParam);
 }
@@ -6852,8 +6996,7 @@
                 if (checkVisible) {
                     if (drawCount !is 0 || !OS.IsWindowVisible (handle)) break;
                     RECT itemRect;
-                    itemRect.left = cast(int) lptvdi.item.hItem;
-                    if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &itemRect) is 0) {
+                    if (!OS.TreeView_GetItemRect (handle, lptvdi.item.hItem, &itemRect, false)) {
                         break;
                     }
                     RECT rect;
@@ -6985,11 +7128,11 @@
             * avoid the operation by testing to see whether
             * the mouse was inside a tree item.
             */
+            if (hooks (DWT.MeasureItem)) return LRESULT.ONE;
             if (hooks (DWT.DefaultSelection)) {
                 POINT pt;
                 int pos = OS.GetMessagePos ();
-                pt.x = cast(short) (pos & 0xFFFF);
-                pt.y = cast(short) (pos >> 16);
+                OS.POINTSTOPOINT (pt, pos);
                 OS.ScreenToClient (handle, &pt);
                 TVHITTESTINFO lpht;
                 lpht.pt.x = pt.x;
@@ -7028,12 +7171,10 @@
             if ((style & DWT.MULTI) !is 0) {
                 if (lockSelection) {
                     /* Save the old selection state for both items */
-                    TVITEM tvItem;
-                    int offset1 = NMHDR.sizeof + 4;
-                    OS.MoveMemory (&tvItem, lParam + offset1, TVITEM.sizeof);
+                    auto treeView = cast(NMTREEVIEW*)lParam;
+                    TVITEM* tvItem = &treeView.itemOld;
                     oldSelected = (tvItem.state & OS.TVIS_SELECTED) !is 0;
-                    int offset2 = NMHDR.sizeof + 4 + TVITEM.sizeof;
-                    OS.MoveMemory (&tvItem, lParam + offset2, TVITEM.sizeof);
+                    tvItem = &treeView.itemNew;
                     newSelected = (tvItem.state & OS.TVIS_SELECTED) !is 0;
                 }
             }
@@ -7045,22 +7186,25 @@
         }
         case OS.TVN_SELCHANGEDA:
         case OS.TVN_SELCHANGEDW: {
+            NMTREEVIEW* treeView = null;
             if ((style & DWT.MULTI) !is 0) {
                 if (lockSelection) {
                     /* Restore the old selection state of both items */
                     if (oldSelected) {
-                        TVITEM tvItem;
-                        int offset = NMHDR.sizeof + 4;
-                        OS.MoveMemory (&tvItem, lParam + offset, TVITEM.sizeof);
+                        if (treeView is null) {
+                            treeView = cast(NMTREEVIEW*)lParam;
+                        }
+                        TVITEM tvItem = treeView.itemOld;
                         tvItem.mask = OS.TVIF_STATE;
                         tvItem.stateMask = OS.TVIS_SELECTED;
                         tvItem.state = OS.TVIS_SELECTED;
                         OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem);
                     }
                     if (!newSelected && ignoreSelect) {
-                        TVITEM tvItem;
-                        int offset = NMHDR.sizeof + 4 + TVITEM.sizeof;
-                        OS.MoveMemory (&tvItem, lParam + offset, TVITEM.sizeof);
+                        if (treeView is null) {
+                            treeView = cast(NMTREEVIEW*)lParam;
+                        }
+                        TVITEM tvItem = treeView.itemNew;
                         tvItem.mask = OS.TVIF_STATE;
                         tvItem.stateMask = OS.TVIS_SELECTED;
                         tvItem.state = 0;
@@ -7069,9 +7213,10 @@
                 }
             }
             if (!ignoreSelect) {
-                TVITEM tvItem;
-                int offset = NMHDR.sizeof + 4 + TVITEM.sizeof;
-                OS.MoveMemory (&tvItem, lParam + offset, TVITEM.sizeof);
+                if (treeView is null) {
+                    treeView = cast(NMTREEVIEW*)lParam;
+                }
+                TVITEM tvItem = treeView.itemNew;
                 hAnchor = tvItem.hItem;
                 Event event = new Event ();
                 event.item = _getItem (&tvItem.hItem, tvItem.lParam);
@@ -7099,9 +7244,9 @@
                 OS.SendMessage (handle, OS.TVM_SETINSERTMARK, 0, 0);
             }
             if (!ignoreExpand) {
-                TVITEM tvItem;
-                int offset = NMHDR.sizeof + 4 + TVITEM.sizeof;
-                OS.MoveMemory (&tvItem, lParam + offset, TVITEM.sizeof);
+                NMTREEVIEW* treeView = cast(NMTREEVIEW*)lParam;
+
+                TVITEM* tvItem = &treeView.itemNew;
                 /*
                 * Feature in Windows.  In some cases, TVM_ITEMEXPANDING
                 * is sent from within TVM_DELETEITEM for the tree item
@@ -7114,9 +7259,7 @@
                 if (item is null) break;
                 Event event = new Event ();
                 event.item = item;
-                int action = *cast(int*)(lParam + NMHDR.sizeof);
-                //OS.MoveMemory (action, lParam + NMHDR.sizeof, 4);
-                switch (action) {
+                switch (treeView.action) {
                     case OS.TVE_EXPAND:
                         /*
                         * Bug in Windows.  When the numeric keypad asterisk
@@ -7176,16 +7319,16 @@
             */
             if (!OS.IsWinCE && OS.COMCTL32_MAJOR >= 6) {
                 if (imageList !is null) {
-                    TVITEM tvItem;
-                    int offset = NMHDR.sizeof + 4 + TVITEM.sizeof;
-                    OS.MoveMemory (&tvItem, lParam + offset, TVITEM.sizeof);
+                    NMTREEVIEW* treeView = cast(NMTREEVIEW*)lParam;
+
+                    TVITEM* tvItem = &treeView.itemNew;
                     if (tvItem.hItem !is null) {
                         int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
                         if ((bits & OS.TVS_FULLROWSELECT) is 0) {
                             RECT rect;
-                            rect.left = cast(int)tvItem.hItem;
-                            OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect);
-                            OS.InvalidateRect (handle, &rect, true);
+                            if (OS.TreeView_GetItemRect (handle, tvItem.hItem, &rect, false)) {
+                                OS.InvalidateRect (handle, &rect, true);
+                            }
                         }
                     }
                 }
@@ -7195,11 +7338,13 @@
         }
         case OS.TVN_BEGINDRAGA:
         case OS.TVN_BEGINDRAGW:
+            if (OS.GetKeyState (OS.VK_LBUTTON) >= 0) break;
+            //FALL THROUGH
         case OS.TVN_BEGINRDRAGA:
         case OS.TVN_BEGINRDRAGW: {
-            TVITEM tvItem;
-            int offset = NMHDR.sizeof + 4 + TVITEM.sizeof;
-            OS.MoveMemory (&tvItem, lParam + offset, TVITEM.sizeof);
+            dragStarted = true;
+            NMTREEVIEW* treeView = cast(NMTREEVIEW*)lParam;
+            TVITEM* tvItem = &treeView.itemNew;
             if (tvItem.hItem !is null && (tvItem.state & OS.TVIS_SELECTED) is 0) {
                 hSelect = tvItem.hItem;
                 ignoreSelect = ignoreDeselect = true;
@@ -7207,7 +7352,6 @@
                 ignoreSelect = ignoreDeselect = false;
                 hSelect = null;
             }
-            dragStarted = true;
             break;
         }
         case OS.NM_RECOGNIZEGESTURE: {
@@ -7244,4 +7388,336 @@
     return super.wmNotifyChild (hdr, wParam, lParam);
 }
 
-}
+LRESULT wmNotifyHeader (NMHDR* hdr, int /*long*/ wParam, int /*long*/ lParam) {
+    /*
+    * Feature in Windows.  On NT, the automatically created
+    * header control is created as a UNICODE window, not an
+    * ANSI window despite the fact that the parent is created
+    * as an ANSI window.  This means that it sends UNICODE
+    * notification messages to the parent window on NT for
+    * no good reason.  The data and size in the NMHEADER and
+    * HDITEM structs is identical between the platforms so no
+    * different message is actually necessary.  Despite this,
+    * Windows sends different messages.  The fix is to look
+    * for both messages, despite the platform.  This works
+    * because only one will be sent on either platform, never
+    * both.
+    */
+    switch (hdr.code) {
+        case OS.HDN_BEGINTRACKW:
+        case OS.HDN_BEGINTRACKA:
+        case OS.HDN_DIVIDERDBLCLICKW:
+        case OS.HDN_DIVIDERDBLCLICKA: {
+            NMHEADER* phdn = cast(NMHEADER*)lParam;
+            TreeColumn column = columns [phdn.iItem];
+            if (column !is null && !column.getResizable ()) {
+                return LRESULT.ONE;
+            }
+            ignoreColumnMove = true;
+            switch (hdr.code) {
+                case OS.HDN_DIVIDERDBLCLICKW:
+                case OS.HDN_DIVIDERDBLCLICKA:
+                    if (column !is null) column.pack ();
+            }
+            break;
+        }
+        case OS.NM_RELEASEDCAPTURE: {
+            if (!ignoreColumnMove) {
+                for (int i=0; i<columnCount; i++) {
+                    TreeColumn column = columns [i];
+                    column.updateToolTip (i);
+                }
+                updateImageList ();
+            }
+            ignoreColumnMove = false;
+            break;
+        }
+        case OS.HDN_BEGINDRAG: {
+            if (ignoreColumnMove) return LRESULT.ONE;
+            NMHEADER* phdn = cast(NMHEADER*)lParam;
+            if (phdn.iItem !is -1) {
+                TreeColumn column = columns [phdn.iItem];
+                if (column !is null && !column.getMoveable ()) {
+                    ignoreColumnMove = true;
+                    return LRESULT.ONE;
+                }
+            }
+            break;
+        }
+        case OS.HDN_ENDDRAG: {
+            NMHEADER* phdn = cast(NMHEADER*)lParam;
+            if (cast(int)phdn.iItem !is -1 && phdn.pitem !is null) {
+                HDITEM* pitem = cast(HDITEM*)phdn.pitem;
+                if ((pitem.mask & OS.HDI_ORDER) !is 0 && pitem.iOrder !is -1) {
+                    int [] order = new int [columnCount];
+                    OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, columnCount, order.ptr);
+                    int index = 0;
+                    while (index < order.length) {
+                        if (order [index] is phdn.iItem) break;
+                        index++;
+                    }
+                    if (index is order.length) index = 0;
+                    if (index is pitem.iOrder) break;
+                    int start = Math.min (index, pitem.iOrder);
+                    int end = Math.max (index, pitem.iOrder);
+                    RECT rect, headerRect;
+                    OS.GetClientRect (handle, &rect);
+                    OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, order [start], &headerRect);
+                    rect.left = Math.max (rect.left, headerRect.left);
+                    OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, order [end], &headerRect);
+                    rect.right = Math.min (rect.right, headerRect.right);
+                    OS.InvalidateRect (handle, &rect, true);
+                    ignoreColumnMove = false;
+                    for (int i=start; i<=end; i++) {
+                        TreeColumn column = columns [order [i]];
+                        if (!column.isDisposed ()) {
+                            column.postEvent (DWT.Move);
+                        }
+                    }
+                }
+            }
+            break;
+        }
+        case OS.HDN_ITEMCHANGINGW:
+        case OS.HDN_ITEMCHANGINGA: {
+            NMHEADER* phdn = cast(NMHEADER*)lParam;
+            if (phdn.pitem !is null) {
+                HDITEM* newItem = cast(HDITEM*)phdn.pitem;
+                if ((newItem.mask & OS.HDI_WIDTH) !is 0) {
+                    RECT rect;
+                    OS.GetClientRect (handle, &rect);
+                    HDITEM oldItem;
+                    oldItem.mask = OS.HDI_WIDTH;
+                    OS.SendMessage (hwndHeader, OS.HDM_GETITEM, phdn.iItem, &oldItem);
+                    int deltaX = newItem.cxy - oldItem.cxy;
+                    RECT headerRect;
+                    OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, phdn.iItem, &headerRect);
+                    int gridWidth = linesVisible ? GRID_WIDTH : 0;
+                    rect.left = headerRect.right - gridWidth;
+                    int newX = rect.left + deltaX;
+                    rect.right = Math.max (rect.right, rect.left + Math.abs (deltaX));
+                    if (explorerTheme || (findImageControl () !is null || hooks (DWT.MeasureItem) || hooks (DWT.EraseItem) || hooks (DWT.PaintItem))) {
+                        rect.left -= OS.GetSystemMetrics (OS.SM_CXFOCUSBORDER);
+                        OS.InvalidateRect (handle, &rect, true);
+                        OS.OffsetRect (&rect, deltaX, 0);
+                        OS.InvalidateRect (handle, &rect, true);
+                    } else {
+                        int flags = OS.SW_INVALIDATE | OS.SW_ERASE;
+                        OS.ScrollWindowEx (handle, deltaX, 0, &rect, null, null, null, flags);
+                    }
+                    if (OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, phdn.iItem, 0) !is 0) {
+                        rect.left = headerRect.left;
+                        rect.right = newX;
+                        OS.InvalidateRect (handle, &rect, true);
+                    }
+                    setScrollWidth ();
+                }
+            }
+            break;
+        }
+        case OS.HDN_ITEMCHANGEDW:
+        case OS.HDN_ITEMCHANGEDA: {
+            NMHEADER* phdn = cast(NMHEADER*)lParam;
+            if (phdn.pitem !is null) {
+                HDITEM* pitem = cast(HDITEM*)phdn.pitem;
+                if ((pitem.mask & OS.HDI_WIDTH) !is 0) {
+                    if (ignoreColumnMove) {
+                        if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) {
+                            int flags = OS.RDW_UPDATENOW | OS.RDW_ALLCHILDREN;
+                            OS.RedrawWindow (handle, null, null, flags);
+                        } else {
+                            if ((style & DWT.DOUBLE_BUFFERED) is 0) {
+                                int oldStyle = style;
+                                style |= DWT.DOUBLE_BUFFERED;
+                                OS.UpdateWindow (handle);
+                                style = oldStyle;
+                            }
+                        }
+                    }
+                    TreeColumn column = columns [phdn.iItem];
+                    if (column !is null) {
+                        column.updateToolTip (phdn.iItem);
+                        column.sendEvent (DWT.Resize);
+                        if (isDisposed ()) return LRESULT.ZERO;
+                        TreeColumn [] newColumns = new TreeColumn [columnCount];
+                        System.arraycopy (columns, 0, newColumns, 0, columnCount);
+                        int [] order = new int [columnCount];
+                        OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, columnCount, order.ptr);
+                        bool moved = false;
+                        for (int i=0; i<columnCount; i++) {
+                            TreeColumn nextColumn = newColumns [order [i]];
+                            if (moved && !nextColumn.isDisposed ()) {
+                                nextColumn.updateToolTip (order [i]);
+                                nextColumn.sendEvent (DWT.Move);
+                            }
+                            if (nextColumn is column) moved = true;
+                        }
+                    }
+                }
+                setScrollWidth ();
+            }
+            break;
+        }
+        case OS.HDN_ITEMCLICKW:
+        case OS.HDN_ITEMCLICKA: {
+            NMHEADER* phdn = cast(NMHEADER*)lParam;
+            TreeColumn column = columns [phdn.iItem];
+            if (column !is null) {
+                column.postEvent (DWT.Selection);
+            }
+            break;
+        }
+        case OS.HDN_ITEMDBLCLICKW:
+        case OS.HDN_ITEMDBLCLICKA: {
+            NMHEADER* phdn = cast(NMHEADER*)lParam;
+            TreeColumn column = columns [phdn.iItem];
+            if (column !is null) {
+                column.postEvent (DWT.DefaultSelection);
+            }
+            break;
+        }
+    }
+    return null;
+}
+
+LRESULT wmNotifyToolTip (NMHDR* hdr, int /*long*/ wParam, int /*long*/ lParam) {
+    if (OS.IsWinCE) return null;
+    switch (hdr.code) {
+        case OS.NM_CUSTOMDRAW: {
+            NMTTCUSTOMDRAW* nmcd = cast(NMTTCUSTOMDRAW*)lParam;
+            return wmNotifyToolTip (nmcd, lParam);
+        }
+        case OS.TTN_SHOW: {
+            LRESULT result = super.wmNotify (hdr, wParam, lParam);
+            if (result !is null) return result;
+            int pos = OS.GetMessagePos ();
+            POINT pt;
+            OS.POINTSTOPOINT (pt, pos);
+            OS.ScreenToClient (handle, &pt);
+            int index;
+            TreeItem item;
+            RECT cellRect, itemRect;
+            if (findCell (pt.x, pt.y, item, index, cellRect, itemRect)) {
+                RECT* toolRect = toolTipRect (&itemRect);
+                OS.MapWindowPoints (handle, null, cast(POINT*)toolRect, 2);
+                int width = toolRect.right - toolRect.left;
+                int height = toolRect.bottom - toolRect.top;
+                int flags = OS.SWP_NOACTIVATE | OS.SWP_NOZORDER | OS.SWP_NOSIZE;
+                if (isCustomToolTip ()) flags &= ~OS.SWP_NOSIZE;
+                SetWindowPos (itemToolTipHandle, null, toolRect.left, toolRect.top, width, height, flags);
+                return LRESULT.ONE;
+            }
+            return result;
+        }
+    }
+    return null;
+}
+
+LRESULT wmNotifyToolTip (NMTTCUSTOMDRAW* nmcd, int /*long*/ lParam) {
+    if (OS.IsWinCE) return null;
+    switch (nmcd.nmcd.dwDrawStage) {
+        case OS.CDDS_PREPAINT: {
+            if (isCustomToolTip ()) {
+                //TEMPORARY CODE
+                //nmcd.uDrawFlags |= OS.DT_CALCRECT;
+                //OS.MoveMemory (lParam, nmcd, NMTTCUSTOMDRAW.sizeof);
+                if (!OS.IsWinCE && OS.WIN32_VERSION < OS.VERSION (6, 0)) {
+                    OS.SetTextColor (nmcd.nmcd.hdc, OS.GetSysColor (OS.COLOR_INFOBK));
+                }
+                return new LRESULT (OS.CDRF_NOTIFYPOSTPAINT | OS.CDRF_NEWFONT);
+            }
+            break;
+        }
+        case OS.CDDS_POSTPAINT: {
+            if (!OS.IsWinCE && OS.WIN32_VERSION < OS.VERSION (6, 0)) {
+                OS.SetTextColor (nmcd.nmcd.hdc, OS.GetSysColor (OS.COLOR_INFOTEXT));
+            }
+            if (OS.SendMessage (itemToolTipHandle, OS.TTM_GETCURRENTTOOL, 0, 0) !is 0) {
+                TOOLINFO lpti;
+                lpti.cbSize = TOOLINFO.sizeof;
+                if (OS.SendMessage (itemToolTipHandle, OS.TTM_GETCURRENTTOOL, 0, cast(int)&lpti) !is 0) {
+                    int index;
+                    TreeItem item;
+                    RECT cellRect, itemRect;
+                    int pos = OS.GetMessagePos ();
+                    POINT pt;
+                    OS.POINTSTOPOINT (pt, pos);
+                    OS.ScreenToClient (handle, &pt);
+                    if (findCell (pt.x, pt.y, item, index, cellRect, itemRect)) {
+                        auto hDC = OS.GetDC (handle);
+                        auto hFont = item.fontHandle (index);
+                        if (hFont is cast(HFONT)-1) hFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0);
+                        HFONT oldFont = OS.SelectObject (hDC, hFont);
+                        LRESULT result = null;
+                        bool drawForeground = true;
+                        cellRect = item.getBounds (index, true, true, false, false, false, hDC);
+                        if (hooks (DWT.EraseItem)) {
+                            Event event = sendEraseItemEvent (item, nmcd, index, &cellRect);
+                            if (isDisposed () || item.isDisposed ()) break;
+                            if (event.doit) {
+                                drawForeground = (event.detail & DWT.FOREGROUND) !is 0;
+                            } else {
+                                drawForeground = false;
+                            }
+                        }
+                        if (drawForeground) {
+                            int nSavedDC = OS.SaveDC (nmcd.nmcd.hdc);
+                            int gridWidth = getLinesVisible () ? Table.GRID_WIDTH : 0;
+                            RECT* insetRect = toolTipInset (&cellRect);
+                            OS.SetWindowOrgEx (nmcd.nmcd.hdc, insetRect.left, insetRect.top, null);
+                            GCData data = new GCData ();
+                            data.device = display;
+                            data.foreground = OS.GetTextColor (nmcd.nmcd.hdc);
+                            data.background = OS.GetBkColor (nmcd.nmcd.hdc);
+                            data.font = Font.win32_new (display, hFont);
+                            GC gc = GC.win32_new (nmcd.nmcd.hdc, data);
+                            int x = cellRect.left + INSET;
+                            if (index !is 0) x -= gridWidth;
+                            Image image = item.getImage (index);
+                            if (image !is null || index is 0) {
+                                Point size = getImageSize ();
+                                RECT imageRect = item.getBounds (index, false, true, false, false, false, hDC);
+                                if (imageList is null) size.x = imageRect.right - imageRect.left;
+                                if (image !is null) {
+                                    Rectangle rect = image.getBounds ();
+                                    gc.drawImage (image, rect.x, rect.y, rect.width, rect.height, x, imageRect.top, size.x, size.y);
+                                    x += INSET + (index is 0 ? 1 : 0);
+                                }
+                                x += size.x;
+                            } else {
+                                x += INSET;
+                            }
+                            String string = item.getText (index);
+                            if (string !is null) {
+                                int flags = OS.DT_NOPREFIX | OS.DT_SINGLELINE | OS.DT_VCENTER;
+                                TreeColumn column = columns !is null ? columns [index] : null;
+                                if (column !is null) {
+                                    if ((column.style & DWT.CENTER) !is 0) flags |= OS.DT_CENTER;
+                                    if ((column.style & DWT.RIGHT) !is 0) flags |= OS.DT_RIGHT;
+                                }
+                                TCHAR[] buffer = StrToTCHARs (getCodePage (), string, false);
+                                RECT textRect;
+                                OS.SetRect (&textRect, x, cellRect.top, cellRect.right, cellRect.bottom);
+                                OS.DrawText (nmcd.nmcd.hdc, buffer.ptr, buffer.length, &textRect, flags);
+                            }
+                            gc.dispose ();
+                            OS.RestoreDC (nmcd.nmcd.hdc, nSavedDC);
+                        }
+                        if (hooks (DWT.PaintItem)) {
+                            itemRect = item.getBounds (index, true, true, false, false, false, hDC);
+                            sendPaintItemEvent (item, nmcd, index, &itemRect);
+                        }
+                        OS.SelectObject (hDC, oldFont);
+                        OS.ReleaseDC (handle, hDC);
+                        if (result !is null) return result;
+                    }
+                    break;
+                }
+            }
+            break;
+        }
+    }
+    return null;
+}
+
+}
--- a/dwt/widgets/TreeColumn.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/TreeColumn.d	Sat May 17 17:34:28 2008 +0200
@@ -17,8 +17,6 @@
 import dwt.events.ControlListener;
 import dwt.events.SelectionEvent;
 import dwt.events.SelectionListener;
-import dwt.graphics.GC;
-import dwt.graphics.GCData;
 import dwt.graphics.Image;
 import dwt.graphics.Rectangle;
 import dwt.internal.win32.OS;
@@ -107,7 +105,10 @@
  * lists the style constants that are applicable to the class.
  * Style bits are also inherited from superclasses.
  * </p>
- *
+ * <p>
+ * Note that due to a restriction on some platforms, the first column
+ * is always left aligned.
+ * </p>
  * @param parent a composite control which will be the parent of the new instance (cannot be null)
  * @param style the style of control to construct
  * @param index the zero-relative index to store the receiver in its parent
@@ -357,35 +358,19 @@
         OS.SendMessage (hwnd, OS.TVM_GETITEM, 0, cast(int) &tvItem);
         TreeItem item = tvItem.lParam !is -1 ? parent.items [tvItem.lParam] : null;
         if (item !is null) {
-            auto hFont = item.cellFont !is null ? item.cellFont [index] : cast(HFONT)-1;
-            if (hFont is cast(HFONT)-1) hFont = item.font;
-            if (hFont !is cast(HFONT)-1) hFont = OS.SelectObject (hDC, hFont);
-            RECT itemRect = item.getBounds (index, true, true, false, false, false, hDC);
-            if (hFont !is cast(HFONT)-1) OS.SelectObject (hDC, hFont);
+            int itemRight = 0;
             if (parent.hooks (DWT.MeasureItem)) {
-                auto nSavedDC = OS.SaveDC (hDC);
-                GCData data = new GCData ();
-                data.device = display;
-                data.hFont = hFont;
-                GC gc = GC.win32_new (hDC, data);
-                Event event = new Event ();
-                event.item = item;
-                event.gc = gc;
-                event.index = index;
-                event.x = itemRect.left;
-                event.y = itemRect.top;
-                event.width = itemRect.right - itemRect.left;
-                event.height = itemRect.bottom - itemRect.top;
-                parent.sendEvent (DWT.MeasureItem, event);
-                event.gc = null;
-                gc.dispose ();
-                OS.RestoreDC (hDC, nSavedDC);
+                Event event = parent.sendMeasureItemEvent (item, index, hDC);
                 if (isDisposed () || parent.isDisposed ()) break;
-                if (event.height > parent.getItemHeight ()) parent.setItemHeight (event.height);
-                //itemRect.left = event.x;
-                itemRect.right = event.x + event.width;
+                itemRight = event.x + event.width;
+            } else {
+                auto hFont = item.fontHandle (index);
+                if (hFont !is cast(HFONT)-1) hFont = OS.SelectObject (hDC, hFont);
+                RECT itemRect = item.getBounds (index, true, true, false, false, false, hDC);
+                if (hFont !is cast(HFONT)-1) OS.SelectObject (hDC, hFont);
+                itemRight = itemRect.right;
             }
-            columnWidth = Math.max (columnWidth, itemRect.right - headerRect.left);
+            columnWidth = Math.max (columnWidth, itemRight - headerRect.left);
         }
         tvItem.hItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, tvItem.hItem);
     }
@@ -490,7 +475,10 @@
  * Controls how text and images will be displayed in the receiver.
  * The argument should be one of <code>LEFT</code>, <code>RIGHT</code>
  * or <code>CENTER</code>.
- *
+ * <p>
+ * Note that due to a restriction on some platforms, the first column
+ * is always left aligned.
+ * </p>
  * @param alignment the new alignment
  *
  * @exception DWTException <ul>
@@ -508,7 +496,7 @@
     auto hwndHeader = parent.hwndHeader;
     if (hwndHeader is null) return;
     HDITEM hdItem;
-    hdItem.mask = OS.HDI_FORMAT | OS.HDI_IMAGE;
+    hdItem.mask = OS.HDI_FORMAT;
     OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem);
     hdItem.fmt &= ~OS.HDF_JUSTIFYMASK;
     if ((style & DWT.LEFT) is DWT.LEFT) hdItem.fmt |= OS.HDF_LEFT;
@@ -623,10 +611,12 @@
                 case DWT.UP:
                     hdItem.fmt &= ~(OS.HDF_IMAGE | OS.HDF_SORTDOWN);
                     hdItem.fmt |= OS.HDF_SORTUP;
+                    if (image is null) hdItem.mask &= ~OS.HDI_IMAGE;
                     break;
                 case DWT.DOWN:
                     hdItem.fmt &= ~(OS.HDF_IMAGE | OS.HDF_SORTUP);
                     hdItem.fmt |= OS.HDF_SORTDOWN;
+                    if (image is null) hdItem.mask &= ~OS.HDI_IMAGE;
                     break;
                 case DWT.NONE:
                     hdItem.fmt &= ~(OS.HDF_SORTUP | OS.HDF_SORTDOWN);
@@ -635,6 +625,7 @@
                         hdItem.iImage = parent.imageIndexHeader (image);
                     } else {
                         hdItem.fmt &= ~OS.HDF_IMAGE;
+                        hdItem.mask &= ~OS.HDI_IMAGE;
                     }
                     break;
                 default:
@@ -681,7 +672,7 @@
     * with spaces.
     */
     auto hHeap = OS.GetProcessHeap ();
-    TCHAR[] buffer = StrToTCHARs (parent.getCodePage (), fixMnemonic (string), true);
+    TCHAR[] buffer = StrToTCHARs (parent.getCodePage (), fixMnemonic (string, true), true);
     int byteCount = buffer.length * TCHAR.sizeof;
     auto pszText = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
     OS.MoveMemory (pszText, buffer.ptr, byteCount);
--- a/dwt/widgets/TreeItem.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/TreeItem.d	Sat May 17 17:34:28 2008 +0200
@@ -58,11 +58,11 @@
     Tree parent;
     String [] strings;
     Image [] images;
+    Font font;
+    Font [] cellFont;
     bool cached;
     int background = -1, foreground = -1;
-    HFONT font = cast(HFONT)-1;
     int [] cellBackground, cellForeground;
-    HFONT[] cellFont;
 
 /**
  * Constructs a new instance of this class given its parent
@@ -258,7 +258,7 @@
         OS.SendMessage (hwnd, OS.TVM_SETITEM, 0, &tvItem);
     }
     background = foreground = -1;
-    HFONT font = cast(HFONT)-1;
+    font = null;
     cellBackground = cellForeground = null;
     cellFont = null;
     if ((parent.style & DWT.VIRTUAL) !is 0) cached = false;
@@ -340,6 +340,12 @@
     releaseHandle ();
 }
 
+HFONT fontHandle (int index) {
+    if (cellFont !is null && cellFont [index] !is null) return cellFont [index].handle;
+    if (font !is null) return font.handle;
+    return cast(HFONT)-1;
+}
+
 /**
  * Returns the receiver's background color.
  *
@@ -444,14 +450,13 @@
     int columnCount = 0;
     auto hwndHeader = parent.hwndHeader;
     if (hwndHeader !is null) {
-        columnCount = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0);
+        columnCount = parent.columnCount;
         firstColumn = index is OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, 0, 0);
     }
     RECT rect;
     if (firstColumn) {
-        rect.left = cast(int) handle;
         bool full = columnCount is 0 && getText && getImage && fullText && fullImage;
-        if (OS.SendMessage (hwnd, OS.TVM_GETITEMRECT, full ? 0 : 1, cast(int)&rect) is 0) {
+        if (!OS.TreeView_GetItemRect (hwnd, handle, &rect, !full)) {
             return RECT.init;
         }
         if (getImage && !fullImage) {
@@ -474,7 +479,7 @@
                     headerRect.right = parent.scrollWidth;
                     if (headerRect.right is 0) headerRect = rect;
                 }
-                if (fullText) rect.right = headerRect.right;
+                if (fullText && clip) rect.right = headerRect.right;
                 if (fullImage) rect.left = headerRect.left;
                 if (clip && headerRect.right < rect.right) {
                     rect.right = headerRect.right;
@@ -487,12 +492,11 @@
         if (OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, cast(int) &headerRect) is 0) {
             return RECT.init;
         }
-        rect.left = cast(int)handle;
-        if (OS.SendMessage (hwnd, OS.TVM_GETITEMRECT, 0, cast(int) &rect) is 0) {
+        if (!OS.TreeView_GetItemRect (hwnd, handle, &rect, false)) {
             return RECT.init;
         }
         rect.left = headerRect.left;
-        if (fullText && getImage) {
+        if (fullText && getImage && clip) {
             rect.right = headerRect.right;
         } else {
             rect.right = headerRect.left;
@@ -507,7 +511,7 @@
                 rect.right += size.x;
             }
             if (getText) {
-                if (fullText) {
+                if (fullText && clip) {
                     rect.left = rect.right + Tree.INSET;
                     rect.right = headerRect.right;
                 } else {
@@ -520,8 +524,7 @@
                         HFONT hFont;
                         if (hDC is null) {
                             hNewDC = OS.GetDC (hwnd);
-                            hFont = cellFont !is null ? cellFont [index] : cast(HFONT)-1;
-                            if (hFont is cast(HFONT)-1) hFont = font;
+                            hFont = fontHandle (index);
                             if (hFont is cast(HFONT)-1) hFont = cast(HFONT) OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0);
                             hFont = OS.SelectObject (hNewDC, hFont);
                         }
@@ -627,7 +630,7 @@
 public Font getFont () {
     checkWidget ();
     if (!parent.checkData (this, true)) error (DWT.ERROR_WIDGET_DISPOSED);
-    return font is cast(HFONT)-1 ? parent.getFont () : Font.win32_new (display, font);
+    return font !is null ? font : parent.getFont ();
 }
 
 /**
@@ -649,8 +652,8 @@
     if (!parent.checkData (this, true)) error (DWT.ERROR_WIDGET_DISPOSED);
     int count = Math.max (1, parent.getColumnCount ());
     if (0 > index || index > count -1) return getFont ();
-    auto hFont = (cellFont !is null) ? cellFont [index] : font;
-    return hFont is cast(HFONT)-1 ? getFont () : Font.win32_new (display, hFont);
+    if (cellFont is null || cellFont [index] is null) return getFont ();
+    return cellFont [index];
 }
 
 /**
@@ -976,8 +979,6 @@
     if (parent.currentItem is this || parent.drawCount !is 0) return;
     auto hwnd = parent.handle;
     if (!OS.IsWindowVisible (hwnd)) return;
-    RECT rect;
-    rect.left = cast(int)handle;
     /*
     * When there are no columns and the tree is not
     * full selection, redraw only the text.  This is
@@ -985,17 +986,15 @@
     */
     bool full = (parent.style & (DWT.FULL_SELECTION | DWT.VIRTUAL)) !is 0;
     if (!full) {
-        auto hwndHeader = parent.hwndHeader;
-        if (hwndHeader !is null) {
-            full = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0) !is 0;
-        }
+        full = parent.columnCount !is 0;
         if (!full) {
             if (parent.hooks (DWT.EraseItem) || parent.hooks (DWT.PaintItem)) {
                 full = true;
             }
         }
     }
-    if (OS.SendMessage (hwnd, OS.TVM_GETITEMRECT, full ? 0 : 1, cast(int) &rect) !is 0) {
+    RECT rect;
+    if (OS.TreeView_GetItemRect (hwnd, handle, &rect, !full)) {
         OS.InvalidateRect (hwnd, &rect, true);
     }
 }
@@ -1178,8 +1177,7 @@
     if ((parent.style & DWT.VIRTUAL) !is 0) {
         if (parent.currentItem is this && OS.IsWindowVisible (hwnd)) {
             RECT rect;
-            rect.left = cast(int) handle;
-            if (OS.SendMessage (hwnd, OS.TVM_GETITEMRECT, 0, cast(int) &rect) !is 0) {
+            if (OS.TreeView_GetItemRect (hwnd, handle, &rect, false)) {
                 OS.InvalidateRect (hwnd, &rect, true);
             }
         }
@@ -1238,20 +1236,17 @@
     */
     RECT oldRect;
     RECT [] rects = null;
-    SCROLLINFO oldInfo;
-    bool oldInfoNull = true;
+    SCROLLINFO* oldInfo;
     int count = 0;
     HANDLE hBottomItem;
     bool redraw = false, noScroll = true;
     HANDLE hTopItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
     if (noScroll && hTopItem !is null) {
-        //oldInfo = new SCROLLINFO ();
-        oldInfoNull = false;
+        oldInfo = new SCROLLINFO ();
         oldInfo.cbSize = SCROLLINFO.sizeof;
         oldInfo.fMask = OS.SIF_ALL;
-        if (!OS.GetScrollInfo (hwnd, OS.SB_HORZ, &oldInfo)) {
-            //oldInfo = null;
-            oldInfoNull = true;
+        if (!OS.GetScrollInfo (hwnd, OS.SB_HORZ, oldInfo)) {
+            oldInfo = null;
         }
         if (parent.drawCount is 0 && OS.IsWindowVisible (hwnd)) {
             bool noAnimate = true;
@@ -1261,8 +1256,7 @@
             int index = 0;
             while (hItem !is null && (noAnimate || hItem !is handle) && index < count) {
                 RECT rect;
-                rect.left = cast(int) hItem;
-                if (OS.SendMessage (hwnd, OS.TVM_GETITEMRECT, 1, cast(int) &rect) !is 0) {
+                if (OS.TreeView_GetItemRect (hwnd, hItem, &rect, true)) {
                     rects [index++] = rect;
                 }
                 hItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, cast(int) &hItem);
@@ -1312,10 +1306,8 @@
         bool collapsed = false;
         if (!expanded) {
             RECT rect;
-            rect.left = cast(int)hTopItem;
-            while (hTopItem !is null && OS.SendMessage (hwnd, OS.TVM_GETITEMRECT, 0, cast(int) &rect) is 0) {
-                rect.left = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hTopItem);
-                hTopItem = cast(HANDLE) rect.left;
+            while (hTopItem !is null && !OS.TreeView_GetItemRect (hwnd, hTopItem, &rect, false)) {
+                hTopItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hTopItem);
                 collapsed = true;
             }
         }
@@ -1324,13 +1316,13 @@
             OS.SendMessage (hwnd, OS.TVM_SELECTITEM, OS.TVGN_FIRSTVISIBLE, hTopItem);
             scrolled = hTopItem !is cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
         }
-        if (!collapsed && !scrolled && !oldInfoNull ) {
+        if (!collapsed && !scrolled && oldInfo !is null ) {
             SCROLLINFO newInfo;
             newInfo.cbSize = SCROLLINFO.sizeof;
             newInfo.fMask = OS.SIF_ALL;
             if (OS.GetScrollInfo (hwnd, OS.SB_HORZ, &newInfo)) {
                 if (oldInfo.nPos !is newInfo.nPos) {
-                    int lParam = OS.SB_THUMBPOSITION | ((oldInfo.nPos << 16) & 0xFFFF0000);
+                    int /*long*/ lParam = OS.MAKELPARAM (OS.SB_THUMBPOSITION, oldInfo.nPos);
                     OS.SendMessage (hwnd, OS.WM_HSCROLL, lParam, 0);
                 }
             }
@@ -1345,8 +1337,7 @@
                     int index = 0;
                     while (hItem !is null && index < count) {
                         RECT rect;
-                        rect.left = cast(int) hItem;
-                        if (OS.SendMessage (hwnd, OS.TVM_GETITEMRECT, 1, cast(int) &rect) !is 0) {
+                        if (OS.TreeView_GetItemRect (hwnd, hItem, &rect, true)) {
                             if (!OS.EqualRect (&rect, & rects [index])) {
                                 break;
                             }
@@ -1376,8 +1367,7 @@
                 }
                 if (handle is hBottomItem) {
                     RECT rect;
-                    rect.left = cast(int) hBottomItem;
-                    if (OS.SendMessage (hwnd, OS.TVM_GETITEMRECT, 0, cast(int)&rect) !is 0) {
+                    if (OS.TreeView_GetItemRect (hwnd, hBottomItem, &rect, false)) {
                         OS.InvalidateRect (hwnd, &rect, true);
                     }
                 }
@@ -1427,13 +1417,11 @@
     if (font !is null && font.isDisposed ()) {
         DWT.error (DWT.ERROR_INVALID_ARGUMENT);
     }
-    HFONT hFont = cast(HFONT)-1;
-    if (font !is null) {
-        parent.customDraw = true;
-        hFont = font.handle;
-    }
-    if (this.font is hFont) return;
-    this.font = hFont;
+    Font oldFont = this.font;
+    if (oldFont is font) return;
+    this.font = font;
+    if (oldFont !is null && oldFont.opEquals (font)) return;
+    if (font !is null) parent.customDraw = true;
     if ((parent.style & DWT.VIRTUAL) !is 0) cached = true;
     /*
     * Bug in Windows.  When the font is changed for an item,
@@ -1479,19 +1467,15 @@
     }
     int count = Math.max (1, parent.getColumnCount ());
     if (0 > index || index > count - 1) return;
-    HFONT hFont = cast(HFONT)-1;
-    if (font !is null) {
-        parent.customDraw = true;
-        hFont = font.handle;
+    if (cellFont is null) {
+        if (font is null) return;
+        cellFont = new Font [count];
     }
-    if (cellFont is null) {
-        cellFont = new HFONT [count];
-        for (int i = 0; i < count; i++) {
-            cellFont [i] = cast(HFONT) -1;
-        }
-    }
-    if (cellFont [index] is hFont) return;
-    cellFont [index] = hFont;
+    Font oldFont = cellFont [index];
+    if (oldFont is font) return;
+    cellFont [index] = font;
+    if (oldFont !is null && oldFont.opEquals (font)) return;
+    if (font !is null) parent.customDraw = true;
     if ((parent.style & DWT.VIRTUAL) !is 0) cached = true;
     /*
     * Bug in Windows.  When the font is changed for an item,
@@ -1633,8 +1617,7 @@
     if ((parent.style & DWT.VIRTUAL) !is 0) {
         if (parent.currentItem is this && OS.IsWindowVisible (hwnd)) {
             RECT rect;
-            rect.left = cast(int)handle;
-            if (OS.SendMessage (hwnd, OS.TVM_GETITEMRECT, 0, cast(int)&rect) !is 0) {
+            if (OS.TreeView_GetItemRect (hwnd, handle, &rect, false)) {
                 OS.InvalidateRect (hwnd, &rect, true);
             }
         }
--- a/dwt/widgets/Widget.d	Mon May 05 00:12:38 2008 +0200
+++ b/dwt/widgets/Widget.d	Sat May 17 17:34:28 2008 +0200
@@ -101,6 +101,15 @@
     static const int FOREIGN_HANDLE = 1<<14;
     static const int DRAG_DETECT    = 1<<15;
 
+    /* Move and resize state flags */
+    static final int MOVE_OCCURRED      = 1<<16;
+    static final int MOVE_DEFERRED      = 1<<17;
+    static final int RESIZE_OCCURRED    = 1<<18;
+    static final int RESIZE_DEFERRED    = 1<<19;
+
+    /* Ignore WM_CHANGEUISTATE */
+    static final int IGNORE_WM_CHANGEUISTATE = 1<<20;
+
     /* Default size for widgets */
     static const int DEFAULT_WIDTH  = 64;
     static const int DEFAULT_HEIGHT = 64;
@@ -197,6 +206,7 @@
  *
  * @see Listener
  * @see DWT
+ * @see #getListeners(int)
  * @see #removeListener(int, Listener)
  * @see #notifyListeners
  */
@@ -357,7 +367,27 @@
 void checkWidget () {
     Display display = this.display;
     if (display is null) error (DWT.ERROR_WIDGET_DISPOSED);
-    if (display.thread !is Thread.getThis ()) error (DWT.ERROR_THREAD_INVALID_ACCESS);
+    if (display.thread !is Thread.getThis ()) {
+        /*
+        * Bug in IBM JVM 1.6.  For some reason, under
+        * conditions that are yet to be full understood,
+        * Thread.currentThread() is either returning null
+        * or a different instance from the one that was
+        * saved when the Display was created.  This is
+        * possibly a JIT problem because modifying this
+        * method to print logging information when the
+        * error happens seems to fix the problem.  The
+        * fix is to use operating system calls to verify
+        * that the current thread is not the Display thread.
+        *
+        * NOTE: Despite the fact that Thread.currentThread()
+        * is used in other places, the failure has only been
+        * observed here.
+        */
+        if (display.threadId !is OS.GetCurrentThreadId ()) {
+            error (DWT.ERROR_THREAD_INVALID_ACCESS);
+        }
+    }
     if ((state & DISPOSED) !is 0) error (DWT.ERROR_WIDGET_DISPOSED);
 }
 
@@ -475,12 +505,17 @@
 }
 
 char [] fixMnemonic (String string) {
-    char [] buffer = string.dup;
+    return fixMnemonic (string, false);
+}
+
+char [] fixMnemonic (String string, bool spaces) {
+    char [] buffer = string ~ '\0';
     int i = 0, j = 0;
     while (i < buffer.length) {
         if (buffer [i] is '&') {
             if (i + 1 < buffer.length && buffer [i + 1] is '&') {
-                buffer [j++] = ' ';
+                if (spaces) buffer [j] = ' ';
+                j++;
                 i++;
             }
             i++;
@@ -577,6 +612,33 @@
     return display;
 }
 
+/**
+ * Returns an array of listeners who will be notified when an event
+ * of the given type occurs. The event type is one of the event constants
+ * defined in class <code>DWT</code>.
+ *
+ * @param eventType the type of event to listen for
+ * @return an array of listeners that will be notified when the event occurs
+ *
+ * @exception DWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @see Listener
+ * @see DWT
+ * @see #addListener(int, Listener)
+ * @see #removeListener(int, Listener)
+ * @see #notifyListeners
+ *
+ * @since 3.4
+ */
+public Listener[] getListeners (int eventType) {
+    checkWidget();
+    if (eventTable is null) return new Listener[0];
+    return eventTable.getListeners(eventType);
+}
+
 Menu getMenu () {
     return null;
 }
@@ -732,6 +794,7 @@
  *
  * @see DWT
  * @see #addListener
+ * @see #getListeners(int)
  * @see #removeListener(int, Listener)
  */
 public void notifyListeners (int eventType, Event event) {
@@ -880,6 +943,7 @@
  * @see Listener
  * @see DWT
  * @see #addListener
+ * @see #getListeners(int)
  * @see #notifyListeners
  */
 public void removeListener (int eventType, Listener listener) {
@@ -999,13 +1063,13 @@
     }
 }
 
-bool sendKeyEvent (int type, int msg, int wParam, int lParam) {
+bool sendKeyEvent (int type, int msg, int /*long*/ wParam, int /*long*/ lParam) {
     Event event = new Event ();
     if (!setKeyState (event, type, wParam, lParam)) return true;
     return sendKeyEvent (type, msg, wParam, lParam, event);
 }
 
-bool sendKeyEvent (int type, int msg, int wParam, int lParam, Event event) {
+bool sendKeyEvent (int type, int msg, int /*long*/ wParam, int /*long*/ lParam, Event event) {
     sendEvent (type, event);
     if (isDisposed ()) return false;
     return event.doit;
@@ -1021,8 +1085,8 @@
     event.button = button;
     event.detail = detail;
     event.count = count;
-    event.x = cast(short) (lParam & 0xFFFF);
-    event.y = cast(short) (lParam >> 16);
+    event.x = OS.GET_X_LPARAM (lParam);
+    event.y = OS.GET_Y_LPARAM (lParam);
     setInputState (event, type);
     mapEvent (hwnd, event);
     if (send) {
@@ -1149,8 +1213,10 @@
     if (OS.GetKeyState (OS.VK_LBUTTON) < 0) event.stateMask |= DWT.BUTTON1;
     if (OS.GetKeyState (OS.VK_MBUTTON) < 0) event.stateMask |= DWT.BUTTON2;
     if (OS.GetKeyState (OS.VK_RBUTTON) < 0) event.stateMask |= DWT.BUTTON3;
-    if (OS.GetKeyState (OS.VK_XBUTTON1) < 0) event.stateMask |= DWT.BUTTON4;
-    if (OS.GetKeyState (OS.VK_XBUTTON2) < 0) event.stateMask |= DWT.BUTTON5;
+    if (display.xMouse) {
+        if (OS.GetKeyState (OS.VK_XBUTTON1) < 0) event.stateMask |= DWT.BUTTON4;
+        if (OS.GetKeyState (OS.VK_XBUTTON2) < 0) event.stateMask |= DWT.BUTTON5;
+    }
     switch (type) {
         case DWT.MouseDown:
         case DWT.MouseDoubleClick:
@@ -1183,7 +1249,7 @@
     return true;
 }
 
-bool setKeyState (Event event, int type, int wParam, int lParam) {
+bool setKeyState (Event event, int type, int /*long*/ wParam, int /*long*/ lParam) {
 
     /*
     * Feature in Windows.  When the user presses Ctrl+Backspace
@@ -1357,16 +1423,16 @@
     int x = 0, y = 0;
     if (lParam !is -1) {
         POINT pt;
-        x = pt.x = cast(short) (lParam & 0xFFFF);
-        y = pt.y = cast(short) (lParam >> 16);
-        OS.ScreenToClient (hwnd, &pt);
+        OS.POINTSTOPOINT (pt, lParam);
+        x = pt.x;
+        y = pt.y;
         RECT rect;
         OS.GetClientRect (hwnd, &rect);
         if (!OS.PtInRect (&rect, pt)) return null;
     } else {
         int pos = OS.GetMessagePos ();
-        x = cast(short) (pos & 0xFFFF);
-        y = cast(short) (pos >> 16);
+        x = OS.GET_X_LPARAM (pos);
+        y = OS.GET_Y_LPARAM (pos);
     }
 
     /* Show the menu */
@@ -1434,7 +1500,22 @@
             default:
         }
     } else {
-        mapKey = OS.MapVirtualKey (wParam, 2);
+        /*
+        * Feature in Windows.  For numbers in Marathi and Bengali,
+        * MapVirtualKey() returns the localized number instead of
+        * the ASCII equivalent.  For example, MapVirtualKey()
+        * maps VK_1 on the Marathi keyboard to \u2407, which is
+        * a valid Unicode Marathi '1' character, but not ASCII.
+        * The fix is to test for VK_0 to VK_9 and map these
+        * explicitly.
+        *
+        * NOTE: VK_0 to VK_9 are the same as ASCII.
+        */
+        if ('0' <= wParam && wParam <= '9') {
+            mapKey = wParam;
+        } else {
+            mapKey = OS.MapVirtualKey (wParam, 2);
+        }
     }
 
     /*
@@ -1718,6 +1799,7 @@
 }
 
 LRESULT wmKillFocus (HWND hwnd, int wParam, int lParam) {
+    display.scrollRemainder = 0;
     int code = callWindowProc (hwnd, OS.WM_KILLFOCUS, wParam, lParam);
     sendFocusEvent (DWT.FocusOut);
     // widget could be disposed at this point
@@ -1766,8 +1848,8 @@
 LRESULT wmLButtonDown (HWND hwnd, int wParam, int lParam) {
     Display display = this.display;
     LRESULT result = null;
-    int x = cast(short) (lParam & 0xFFFF);
-    int y = cast(short) (lParam >> 16);
+    int x = OS.GET_X_LPARAM (lParam);
+    int y = OS.GET_Y_LPARAM (lParam);
     bool [] consume = null, detect = null;
     bool dragging = false, mouseDown = true;
     int count = display.getClickCount (DWT.MouseDown, 1, hwnd, lParam);
@@ -1871,7 +1953,7 @@
     */
     int mask = OS.MK_LBUTTON | OS.MK_MBUTTON | OS.MK_RBUTTON;
     if (display.xMouse) mask |= OS.MK_XBUTTON1 | OS.MK_XBUTTON2;
-    if (((wParam & 0xFFFF) & mask) is 0) {
+    if ((wParam & mask) is 0) {
         if (OS.GetCapture () is hwnd) OS.ReleaseCapture ();
     }
     return result;
@@ -1937,7 +2019,7 @@
     */
     int mask = OS.MK_LBUTTON | OS.MK_MBUTTON | OS.MK_RBUTTON;
     if (display.xMouse) mask |= OS.MK_XBUTTON1 | OS.MK_XBUTTON2;
-    if (((wParam & 0xFFFF) & mask) is 0) {
+    if ((wParam & mask) is 0) {
         if (OS.GetCapture () is hwnd) OS.ReleaseCapture ();
     }
     return result;
@@ -1954,10 +2036,9 @@
     if (!hooks (DWT.MouseExit) && !filters (DWT.MouseExit)) return null;
     int pos = OS.GetMessagePos ();
     POINT pt;
-    pt.x = cast(short) (pos & 0xFFFF);
-    pt.y = cast(short) (pos >> 16);
+    OS.POINTSTOPOINT (pt, pos);
     OS.ScreenToClient (hwnd, &pt);
-    lParam = (pt.x & 0xFFFF) | ((pt.y << 16) & 0xFFFF0000);
+    lParam = OS.MAKELPARAM (pt.x, pt.y);
     if (!sendMouseEvent (DWT.MouseExit, 0, hwnd, OS.WM_MOUSELEAVE, wParam, lParam)) {
         return LRESULT.ZERO;
     }
@@ -2017,30 +2098,37 @@
 }
 
 LRESULT wmMouseWheel (HWND hwnd, int wParam, int lParam) {
-    if (!hooks (DWT.MouseWheel) && !filters (DWT.MouseWheel)) return null;
-    int delta = wParam >> 16;
-    int value;
-    int count, detail;
-    OS.SystemParametersInfo (OS.SPI_GETWHEELSCROLLLINES, 0, &value, 0);
-    if (value is OS.WHEEL_PAGESCROLL) {
+    int delta = OS.GET_WHEEL_DELTA_WPARAM (wParam);
+    int linesToScroll;
+    int detail;
+    OS.SystemParametersInfo (OS.SPI_GETWHEELSCROLLLINES, 0, &linesToScroll, 0);
+    if (linesToScroll is OS.WHEEL_PAGESCROLL) {
         detail = DWT.SCROLL_PAGE;
-        count = delta / OS.WHEEL_DELTA;
     } else {
         detail = DWT.SCROLL_LINE;
-        count = value * delta / OS.WHEEL_DELTA;
+        delta *= linesToScroll;
     }
+    /* Check if the delta and the remainder have the same direction (sign) */
+    if ((delta ^ display.scrollRemainder) >= 0) delta += display.scrollRemainder;
+    display.scrollRemainder = delta % OS.WHEEL_DELTA;
+
+    if (!hooks (DWT.MouseWheel) && !filters (DWT.MouseWheel)) return null;
+    int count = delta / OS.WHEEL_DELTA;
     POINT pt;
-    pt.x = cast(short) (lParam & 0xFFFF);
-    pt.y = cast(short) (lParam >> 16);
+    OS.POINTSTOPOINT (pt, lParam);
     OS.ScreenToClient (hwnd, &pt);
-    lParam = (pt.x & 0xFFFF) | ((pt.y << 16) & 0xFFFF0000);
+    lParam = OS.MAKELPARAM (pt.x, pt.y);
     if (!sendMouseEvent (DWT.MouseWheel, 0, count, detail, true, hwnd, OS.WM_MOUSEWHEEL, wParam, lParam)) {
         return LRESULT.ZERO;
     }
     return null;
 }
 
-LRESULT wmPaint (HWND hwnd, int wParam, int lParam) {
+LRESULT wmNCPaint (HWND hwnd, int /*long*/ wParam, int /*long*/ lParam) {
+    return null;
+}
+
+LRESULT wmPaint (HWND hwnd, int /*long*/ wParam, int /*long*/ lParam) {
 
     /* Exit early - don't draw the background */
     if (!hooks (DWT.Paint) && !filters (DWT.Paint)) {
@@ -2048,7 +2136,7 @@
     }
 
     /* Issue a paint event */
-    int result = 0;
+    int /*long*/ result = 0;
     static if (OS.IsWinCE) {
         RECT rect;
         OS.GetUpdateRect (hwnd, &rect, false);
@@ -2132,7 +2220,7 @@
         if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) {
             int bits = OS.GetWindowLong (hwnd, OS.GWL_EXSTYLE);
             if ((bits & OS.WS_EX_CLIENTEDGE) !is 0) {
-                int code = callWindowProc (hwnd, OS.WM_PRINT, wParam, lParam);
+                int /*long*/ code = callWindowProc (hwnd, OS.WM_PRINT, wParam, lParam);
                 RECT rect;
                 OS.GetWindowRect (hwnd, &rect);
                 rect.right -= rect.left;
@@ -2210,14 +2298,14 @@
     */
     int mask = OS.MK_LBUTTON | OS.MK_MBUTTON | OS.MK_RBUTTON;
     if (display.xMouse) mask |= OS.MK_XBUTTON1 | OS.MK_XBUTTON2;
-    if (((wParam & 0xFFFF) & mask) is 0) {
+    if ((wParam & mask) is 0) {
         if (OS.GetCapture () is hwnd) OS.ReleaseCapture ();
     }
     return result;
 }
 
 LRESULT wmSetFocus (HWND hwnd, int wParam, int lParam) {
-    int code = callWindowProc (hwnd, OS.WM_SETFOCUS, wParam, lParam);
+    int /*long*/ code = callWindowProc (hwnd, OS.WM_SETFOCUS, wParam, lParam);
     sendFocusEvent (DWT.FocusIn);
     // widget could be disposed at this point
 
@@ -2246,7 +2334,7 @@
     /* Call the window proc to determine whether it is a system key or mnemonic */
     bool oldKeyHit = display.mnemonicKeyHit;
     display.mnemonicKeyHit = true;
-    int result = callWindowProc (hwnd, OS.WM_SYSCHAR, wParam, lParam);
+    int /*long*/ result = callWindowProc (hwnd, OS.WM_SYSCHAR, wParam, lParam);
     bool consumed = false;
     if (!display.mnemonicKeyHit) {
         consumed = !sendKeyEvent (DWT.KeyDown, OS.WM_SYSCHAR, wParam, lParam);
@@ -2405,7 +2493,7 @@
     LRESULT result = null;
     Display display = this.display;
     display.captureChanged = false;
-    int button = (wParam >> 16 is OS.XBUTTON1) ? 4 : 5;
+    int button = OS.HIWORD (wParam) is OS.XBUTTON1 ? 4 : 5;
     sendMouseEvent (DWT.MouseDown, button, hwnd, OS.WM_XBUTTONDOWN, wParam, lParam);
     if (sendMouseEvent (DWT.MouseDoubleClick, button, hwnd, OS.WM_XBUTTONDBLCLK, wParam, lParam)) {
         result = new LRESULT (callWindowProc (hwnd, OS.WM_XBUTTONDBLCLK, wParam, lParam));
@@ -2423,7 +2511,7 @@
     Display display = this.display;
     display.captureChanged = false;
     display.xMouse = true;
-    int button = (wParam >> 16 is OS.XBUTTON1) ? 4 : 5;
+    int button = OS.HIWORD (wParam) is OS.XBUTTON1 ? 4 : 5;
     if (sendMouseEvent (DWT.MouseDown, button, hwnd, OS.WM_XBUTTONDOWN, wParam, lParam)) {
         result = new LRESULT (callWindowProc (hwnd, OS.WM_XBUTTONDOWN, wParam, lParam));
     } else {
@@ -2438,7 +2526,7 @@
 LRESULT wmXButtonUp (HWND hwnd, int wParam, int lParam) {
     Display display = this.display;
     LRESULT result = null;
-    int button = (wParam >> 16 is OS.XBUTTON1) ? 4 : 5;
+    int button = OS.HIWORD (wParam) is OS.XBUTTON1 ? 4 : 5;
     if (sendMouseEvent (DWT.MouseUp, button, hwnd, OS.WM_XBUTTONUP, wParam, lParam)) {
         result = new LRESULT (callWindowProc (hwnd, OS.WM_XBUTTONUP, wParam, lParam));
     } else {
@@ -2452,7 +2540,7 @@
     */
     int mask = OS.MK_LBUTTON | OS.MK_MBUTTON | OS.MK_RBUTTON;
     if (display.xMouse) mask |= OS.MK_XBUTTON1 | OS.MK_XBUTTON2;
-    if (((wParam & 0xFFFF) & mask) is 0) {
+    if ((wParam & mask) is 0) {
         if (OS.GetCapture () is hwnd) OS.ReleaseCapture ();
     }
     return result;